线程队列 线程池 协程

1 . 线程队列

from multiprocessing Queue , JoinableQueue  #进程IPC队列

from queue import Queue  #线程队列  先进先出

from queue import LifoQueue  #后进先出的

方法都是一样的 : put , get , put_nowait , get_nowait , full , empty , qsize

队列 Queue : 先进先出 , 自带锁 , 数据安全

栈 LifoQueue : 后进先出 , 自带锁 , 数据安全

q = LifoQueue(5)

q.put(3)

q.put_nowait(4)

print(q.get())  #谁最后进的,就会先取谁

q.get_nowait()

print(q.full())

pirnt(q.empty())

print(q.qsize())

from queue import PriorityQueue  #优先级队列

q = PriorityQueue()

q.put((10,"aaa"))

q.put((4,"bbb"))

print(q.get())

线程池

Threading 没有线程池的

Multiprocessing Pool

concurrent.futures  帮助管理线程池和进程池

import time

from threading import currentThread,get_ident

from concurrent.futures import ThreadPoolExecutor  #帮助启动线程池

from concurrent.futures import ProcessPoolExecutor  #帮助启动进程池

def func(i):

  time.sleep(1)

  print("in%s%s"%(i,currentThread()))

  return i**2

def back(fn):

  print(fn.result(),currentThread())

#map启动多线程任务

t = ThreadPoolExecutor(5)

t.map(func,range(20))      ==     for i in range(20):

                     t.submit(func,i)

#submit异步提交任务

t = ThreadPoolExecutor(5)

for i in range(20):

  t.submit(func,i)

t.shutdown()

print("main:",currentThread())  #起多少个线程池 , 5*CPU的个数

#获取任务结果

t = ThreadPoolExecutor(5)

li = []

for i in range(20):

  ret = t.submit(func,i)

  li.append(ret)

t.shutdown()

for i in li:

  print(i.result())

print("main:",currentThread())

#回调函数

t = ThreadPoolExecutor(5)

for i in range(20):

  t.submit(func,i).add_done_callback(back)

#回调函数(进程版)

import os,time

from concurrent.futures import ProcessPoolExecutor

def func(i):

  print("in%s%s"%(i,os.getpid()))

  return i**2

def back(fn):

  print(fn.result(),os.getpid())

if __name__ == "__main__":

  p = ProcessPoolExecutor(5)

  for i in range(20):

    p.submit(func,i).add_done_callback(back)

  print("main:",os.getpid())

multiprocessing模块自带进程池的

threading模块是没有线程池的

concurrent.futures 进程池和线程池 : 高度封装 , 进程池/线程池的统一的使用方式

创建线程池/进程池 ProcessPoolExecutor  ThreadPoolExecutor

ret .result()获取结果,如果想实现异步效果,应该使用列表

shutdown  == close + join 同步控制

add_done_callback 回调函数,在回调函数内接收的参数是一个对象,需要通过result来获取返回值. 进程池的回调函数仍然在主进程中执行,但是线程池的回调函数是在线程中执行.

进程 : 资源分配的最小单位  ,  班级

线程 : CPU调度最小单位 , 人

Cpython线程不能利用多核的 ,多线程无法利用多核 ,一个线程能同时执行多个任务.

协程 : 能在一条线程的基础上 ,再过个任务之间互相切换 .节省了线程开启的消耗.

协程是从python代码的级别调度的 , 正常的线程是CPU调度的最小单位 ; 协程的调度并不是由操作系统来完成的.

之前学过的协程在两个任务之间相互切换的是生成器函数:yield

def func():

  print(1)

  x = yield "aaa"

  print(x)

  yield  "bbb"

g  = func()

print(next(g))

print(g.send("***"))

在多个函数之间互相切换的功能  ---  协程

def consumer():

  while True:

    x = yield

    print(x)

def producer():

  g = consumer()

  next(g)    #预激

  for i in range(20):

    g.send(i)

producer()

yield只有程序之间的切换,没有重利用任何IO操作的时间

模块的安装 :

pip3 install 要安装的模块的名字

使用协程减少IO操作带来的时间消耗

from gevent import monkey ; monkey.patch_all()

import gevent,time

def eat():

  print("吃")

  time.sleep(2)

  print("吃完了")

def play():

  print("玩")

  time.sleep(1)

  print("玩完了")

g1 = gevent.spawn(eat)

g2 = gevent.spawn(play)

gevent.joinall([g1,g2])

没有执行 , 为什么没执行???是需要开启么?

没有开启但是切换了

gevent帮我们做了切换,做切换是有条件的,遇到IO才切换

gevent不认识除了gevent这个模块内以外的IO操作

使用join可以一直阻塞直到协程任务完成

帮助gevent来认识其他模块中的阻塞

from gevent import monkey;monkey.patch_all() 写在其他模块导入之前.

使用协程来实现TCP协议 :

服务器 :

from gevent import monkey;monkey.patch_all()

import gevent,socket

def func(conn):

  while 1:

    conn.send(b"hello")

    print(conn.recv(1024))

sk = socket.socket()

sk.bind(("127.0.0.1",9090))

sk.listen()

while 1:

  conn,addr = sk.accept()

  gevent.spawn(func,conn)

客户端 :

import socket

from threading import Thread

def client():

  sk = socket.socket()

  sk.connect(("127.0.0.1",9090))

  while 1:

    print(sk.recv(1024))

    sk.send(b"bye")

for i in range(20):

  Thread(target=client).start()

4c 并发50000  qps

5个进程

20个线程

500个协程

协程能够在单核的情况极大地提高CPU的利用率

协程不存在数据不安全 , 也不存在线程切换/创造的时间开销 ; 切换时用户级别的,程序不会因为协程中某一个任务进入阻塞状态而使整条线程阻塞

线程的切换 :

时间片到了 降低了CPU的效率

IO会切  提高了CPU的效率

原文地址:https://www.cnblogs.com/fengkun125/p/9403360.html

时间: 2024-07-31 17:31:22

线程队列 线程池 协程的相关文章

进程池线程池 协程

socket服务端实现并发 服务端需要满足以下3点: 1 固定的ip和port 2 24小时提供服务 3 能够实现并发 多线程实现并发: 服务端: import socket from threading import Thread import os server = socket.socket() server.bind(('127.0.0.1',8080)) server.listen(5) #半连接池 def communicate(conn): while True: try: dat

Python:线程、进程与协程(4)——multiprocessing模块(1)

multiprocessing模块是Python提供的用于多进程开发的包,multiprocessing包提供本地和远程两种并发,通过使用子进程而非线程有效地回避了全局解释器锁. (一)创建进程Process 类 创建进程的类,其源码在multiprocessing包的process.py里,有兴趣的可以对照着源码边理解边学习.它的用法同threading.Thread差不多,从它的类定义上就可以看的出来,如下: class Process(object):     '''     Proces

Python之路【第七篇】:线程、进程和协程

Python之路[第七篇]:线程.进程和协程 Python线程 Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #!/usr/bin/env python # -*- coding:utf-8 -*- import threading import time   def show(arg):     time.sleep(1)     print 'thread'+str(arg)   for i in

Python菜鸟之路:Python基础-线程、进程、协程

上节内容,简单的介绍了线程和进程,并且介绍了Python中的GIL机制.本节详细介绍线程.进程以及协程的概念及实现. 线程 基本使用 方法1: 创建一个threading.Thread对象,在它的初始化函数(__init__)中将可调用对象作为参数传入 import threading import time def worker(): time.sleep(2) print("test") for i in range(5): t = threading.Thread(target=

Python:线程、进程与协程(3)——Queue模块及源码分析

Queue模块是提供队列操作的模块,队列是线程间最常用的交换数据的形式.该模块提供了三种队列: Queue.Queue(maxsize):先进先出,maxsize是队列的大小,其值为非正数时为无线循环队列 Queue.LifoQueue(maxsize):后进先出,相当于栈 Queue.PriorityQueue(maxsize):优先级队列. 其中LifoQueue,PriorityQueue是Queue的子类.三者拥有以下共同的方法: qsize():返回近似的队列大小.为什么要加"近似&q

Python:线程、进程与协程(1)——概念

最近的业余时间主要放在了学习Python线程.进程和协程里,第一次用python的多线程和多进程是在两个月前,当时只是简单的看了几篇博文然后就跟着用,没有仔细去研究,第一次用的感觉它们其实挺简单的,最近这段时间通过看书, 看Python 中文官方文档等等相关资料,发现并没有想想中的那么简单,很多知识点需要仔细去理解,Python线程.进程和协程应该是Python的高级用法.Python的高级用法有很多,看看Python 中文官方文档就知道了,当然有时间看看这些模块是怎么实现的对自己的提高是很有帮

线程、进程与协程2

一.协程 什么是协程? 协程,又名微线程,纤程,英文名为Coroutine. 协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈. 因此,协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置. CPU只认识线程,不认识协程.线程的寄存器在CPU上,协程的寄存器不在CPU上. yield就是在

Python:线程、进程与协程(2)——threading模块(1)

上一篇博文介绍了Python中线程.进程与协程的基本概念,通过这几天的学习总结,下面来讲讲Python的threading模块.首先来看看threading模块有哪些方法和类吧. 主要有: Thread :线程类,这是用的最多的一个类,可以指定线程函数执行或者继承自它都可以实现子线程功能. Timer:与Thread类似,但要等待一段时间后才开始运行,是Thread的子类. Lock :原锁,是一个同步原语,当它锁住时不归某个特定的线程所有,这个可以对全局变量互斥时使用. RLock :可重入锁

线程、进程、协程和GIL(一)

参考链接:https://www.cnblogs.com/alex3714/articles/5230609.html https://www.cnblogs.com/work115/p/5620272.html 编程离不开并发,而并发的基础就离不开线程.进程.协程.那么什么是线程.进程.协程呢? 进程: 进程是对资源进行分配和调度的最小单位,是操作系统结构的基础,是线程的容器(就像是一幢房子,一个空壳子,并不能运动). 线程的概念主要有两点: 1.进程是一个实体,每个进程都有自己的地址空间,一