进程池:限制进程创建的数量,使用时直接从进程池,获取空闲进程去执行任务,减少创建和销毁进程带来的时间消耗;如果进程的数量没有达到最大数量,且没有空闲进程去执行 任务,就会再创建一个新的进程,放入进程池去执行任务;
如果进程池中的进程数量达到最大数量,没有空闲进程去,这是任务需要等待某个进程成为空闲进程之后,再去执行任务。
from concurrent.futures import ProcessPoolExecutor import time import os # 池子中创建的进程/线程创建会被保存在进程/线程池中 # 会调用进程/线程池中的进程/线程去执行任务 # 节省了反复开辟进程/线程的资源 pool = ProcessPoolExecutor() # 默认是当前计算机cpu的个数 def task(n): print(n,os.getpid()) # 查看当前进程号 time.sleep(2) if __name__ == ‘__main__‘: for i in range(20): res = pool.submit(task,i)
ps:当进程池满后,没有kill进程的情况下,会使用进程池中的进程去执行任务,不会再去创建新的进程。
线程池:同进程池概念类似。
from concurrent.futures import ThreadPoolExecutor import time # 池子中创建的进程/线程创建会被保存在进程/线程池中 # 会调用进程/线程池中的进程/线程去执行任务 # 节省了反复开辟进程/线程的资源 pool = ThreadPoolExecutor(5) # 括号内可以传参数指定线程池内的线程个数 # 也可以不传 不传默认是当前所在计算机的cpu个数乘5 def task(n): print(n) # 查看当前进程号 time.sleep(2) for i in range(20): res = pool.submit(task,i)
进程异步:
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor import time import os pool = ProcessPoolExecutor() # 默认是当前计算机cpu的个数 # 池子中创建的进程/线程创建会被保存在进程/线程池中 # 会调用进程/线程池中的进程/线程去执行任务 # 节省了反复开辟进程/线程的资源 def task(n): print(n,os.getpid()) # 查看当前进程号 time.sleep(2) return n**2 def call_back(n): print(‘拿到了异步提交任务的返回结果:‘,n.result()) """ 提交任务的方式 同步:提交任务之后 原地等待任务的返回结果 期间不做任何事 异步:提交任务之后 不等待任务的返回结果 通过回调方式获得异步返回值 直接执行下一行代码 """ """ 异步回调机制:当异步提交的任务有返回结果之后,会自动触发回调函数的执行 """ if __name__ == ‘__main__‘: t_list = [] for i in range(20): res = pool.submit(task,i).add_done_callback(call_back) # 提交任务的时候 绑定一个回调函数 一旦该任务有结果 立刻执行对于的回调函数 t_list.append(res)
线程异步:
from concurrent.futures import ThreadPoolExecutor import time import os pool = ThreadPoolExecutor(5) # 括号内可以传参数指定线程池内的线程个数 def task(n): print(n,os.getpid()) # 查看当前进程号 time.sleep(2) return n**2 def call_back(n): print(‘拿到了异步提交任务的返回结果:‘,n.result()) # 异步回调机制:当异步提交的任务有返回结果之后,会自动触发回调函数的执行 for i in range(20): res = pool.submit(task,i).add_done_callback(call_back) # 提交任务的时候 绑定一个回调函数 一旦该任务有结果 立刻执行对于的回调函数
协程(Coroutine):是单线程下的并发,又称微线程。
协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。
协程的本质 :就是在单线程下,由用户自己控制一个任务遇到io阻塞了就切换另外一个任务去执行,以此来提升效率。
优点:
1. 协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级
2. 单线程内就可以实现并发的效果,最大限度地利用cpu
缺点:
1. 协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程
2. 协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程
单线程多协程TCP
服务端
from gevent import monkey;monkey.patch_all() import socket from gevent import spawn server = socket.socket() server.bind((‘127.0.0.1‘,8080)) server.listen(5) def talk(conn): while True: try: data = conn.recv(1024) if len(data) == 0:break print(data.decode(‘utf-8‘)) conn.send(data.upper()) except ConnectionResetError as e: print(e) break conn.close() def server1(): while True: conn, addr = server.accept() spawn(talk,conn) if __name__ == ‘__main__‘: g1 = spawn(server1) g1.join()
客户端
import socket from threading import Thread,current_thread def client(): client = socket.socket() client.connect((‘127.0.0.1‘,8080)) n = 0 while True: data = ‘%s %s‘%(current_thread().name,n) client.send(data.encode(‘utf-8‘)) res = client.recv(1024) print(res.decode(‘utf-8‘)) n += 1 for i in range(400): t = Thread(target=client) t.start()
原文:https://www.cnblogs.com/Cpsyche/p/11360078.html