开进程开线程都需要消耗资源,只不过两者比较的情况线程消耗的资源比较少
在计算机能够承受范围之内最大限度的利用计算机
什么是池?
在保证计算机硬件安全的情况下最大限度地利用计算机
池其实是降低了程序的运行效率 但是保证了计算机硬件的安全
(硬件的发展跟不上软件的速度)
线程池进程池
括号内可以传参数指定线程池内的线程个数
也可以不传 不传默认是当前cpu核数*5
提交任务的方式:
同步:提交任务之后,原地等待任务的结果,期间不做任何事
异步:提交任务后,不等待任务的返回结果(异步的结果怎么拿?),直接执行下一行代码
这(.add_done_callback())其实是 .submit() 返回结果对象的方法
异步回调机制:当异步提交的任务有返回结果之后,会自动触发回调函数的执行
import random import time import os from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor from threading import current_thread def callback(future): print(f"我拿到了回调结果:{future.result()}") def task(i): time.sleep(random.random()) # print(f"{os.getpid()} {i} is over...") print(f"{os.getpid()} {current_thread().name} {i} is over...") return f"{i}² = {i * i}" if __name__ == '__main__': # 进程池的时候一定要放在这里面 # pool = ProcessPoolExecutor(3) pool = ThreadPoolExecutor(3, 'MyThreading') future_list = [] for i in range(5): # ----------------------------------------------------- # .submit().add_done_callback() 自动调用回调函数 # 会自动将 .submit()的返回结果作为参数传给.add_done_callback() 中传入的函数去调用执行 # .add_done_callback() 其实是 .submit()返回对象自身的方法 # ----------------------------------------------------- future = pool.submit(task, i).add_done_callback(callback) future_list.append(future) pool.shutdown() # 关闭池子且等待池子中所有的任务运行完毕 print("主") # 11348 MyThreading_0 0 is over... # 我拿到了回调结果:0² = 0 # 11348 MyThreading_2 2 is over... # 我拿到了回调结果:2² = 4 # 11348 MyThreading_0 3 is over... # 我拿到了回调结果:3² = 9 # 11348 MyThreading_1 1 is over... # 我拿到了回调结果:1² = 1 # 11348 MyThreading_2 4 is over... # 我拿到了回调结果:4² = 16 # 主协程
进程:资源单位 线程:执行单位 协程:单线程下实现并发
并发 切换+保存状态 ps:看起来像同时执行的 就可以称之为并发
协程:完全是程序员自己意淫出来的名词 单线程下实现并发
并发的条件? 多道技术 空间上的复用 时间上的复用 切换+保存状态
程序员自己通过代码自己检测程序中的IO 一旦遇到IO自己通过代码切换 给操作系统的感觉是你这个线程没有任何的IO ps:欺骗操作系统 让它误认为你这个程序一直没有IO 从而保证程序在运行态和就绪态来回切换 提升代码的运行效率
切换+保存状态就一定能够提升效率吗??? 当你的任务是iO密集型的情况下 提升效率 如果你的任务是计算密集型的 降低效率
yield 保存上一次的结果
多进程下开多线程 多线程下再开协程
下载安装
gevent基本介绍
from gevent import spawn, monkey monkey.patch_all() # 一般这个要写在很前面(例如导socket模块之前) # 两行亦可写成一行 from gevent import monkey;monkey.patch_all() g1 = spawn(eat, 1, 2, 3, x=4, y=5) # 创建一个协程对象g1,spawn括号内第一个参数是函数名,如eat,后面是该函数(eat)所需要的参数 g2 = spawn(func2) g1.join() # 等待协程g1结束 g2.join() # 等待协程g2结束 # 上述两步亦可合作一步:joinall([g1,g2]) g1.value # 拿到func1的返回值在计算密集型任务中使用
from gevent import spawn, monkey monkey.patch_all() import time def func1(): for i in range(10000000): i + 1 def func2(): for i in range(10000000): i + 1 start = time.time() g = spawn(func1) g2 = spawn(func2) g.join() g2.join() stop = time.time() print(stop - start) # 1.1324069499969482 # 与前面普通的串行执行时间 1.2481744289398193 相近 # spawn 可以让操作系统察觉不到这个程序有IO操作利用gevent在单线程下实现并发
服务端
import socket from gevent import spawn from gevent import monkey # 让 gevent 能够识别python的 IO monkey.patch_all() 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 wait_client_connect(): while True: conn, addr = server.accept() spawn(talk, conn) if __name__ == '__main__': g1 = spawn(wait_client_connect) g1.join() # 别忘了加上客户端
import socket from threading import Thread, current_thread def create_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): # 手动开400个线程连接客户端(测试的是服务端单线程实现并发) t = Thread(target=create_client) t.start() 最大程度下提高代码的执行效率(实现高并发) 多进程下使用多线程 多线程下使用多协程 **大前提** IO密集型任务(了解)
让select帮你去要数据,你做自己的事,有数据了给你
转载于:https://www.cnblogs.com/PowerTips/p/11355980.html
相关资源:NordicSemiconductor.nRF_DeviceFamilyPack.8.15.2.pack