其他分享
首页 > 其他分享> > day38

day38

作者:互联网

day38     在线程池和进程池中,每次提交任务,都会返回一个表示任务的对象FUture对象 Future对象具体一个绑定方法,add_done_callback用于指定的回调函数 如何直接使用thread的话,如何完成回调   def call_back(res)     print("%s" % res)       def task(callback):     print("run")     return 100     res = 100     callback(res) #执行回调函数,并传入任务结果   t = Thread(target=task,args=(call_back,))#调上面那个函数 t.start()     异步回调原理   ??????在发起任务时候,传入一个函数(call_back)作为回调函数,在任务完成后,执行该函数,并将执行结果作为参数(callback)传入   如果是进程的回调,还需要考虑数据通讯的问题,最难的是让父进程在拿到结果的时候立即触发回调的函数的执行,父进程不应该卡住.       ###今日内容 1.线程一堆队列 Queue   lifoqueue后进先出队列    顺序不一样 prioityQueue具备优先级的队列  (可以存储一个可迭代对象,可以比较大小)   优先级高(值越小,字符串也可以)的先出  ,自定义对象不能使用比较运算符,不能存储 2.事件event 表示发生了某些事情,可以去关注某个事件,采取一些行动. 事件本质上是用来线程间通讯,用于状态同步. 案例: 有两条线程,一个用于启动服务器,一个是用户客户端连接到服务器. 条件是服务器启动成功,客户端才能连接成功. #代码 爬虫,开视频窗口,数量小于5就开,大于5就不开. while True:     判断视频的窗口是否为5:     true:event.clear()          false:event.set()   3.协程***** 协程的目的就是要在单线程的实现并发 单线程实现并发 并发:多个任务看起来是同时运行,本质是切换+保存状态   生成器中yield就可以保存当前函数的运行状态, def func1():     yield res = func1() next(res)   ##代码 并发代码 import time     def func1():     a = 1     for i in range(11111111111):     a+=1     yield     def func2():     res = func1()     a = 1     for i in range(11111111111):     a+=1     next(res) st = time.time() func2() print(time.time()-st) #串行代码   经过测试,单线程并发并不能提高性能,对于计算密集型任务而言 对于IO操作而言,必须要具备检测IO操作 并自动切换成其他任务.这才能真正的提高效率. greenlet 直接使用yiled可以并发,但是代码结构太乱, ????????   gevent ##什么是协程 轻量级线程,也称之为微线程,是应用程序级别的任务调度方式   应用程序级别调度:检测到IO操作时,立马切换到我的其他任务来执行,如果有足够的任务来执行,就可以                             把cpu的时间片充分利用起来. 操作系统级别的调度:遇到IO操作系统就回拿走cpu,下次分给哪个进程就不一定了     线程,最小执行单位,可以解决一定数量的并发问题,但是如果线程数量达到上限,后续任务必须等待. 对于IO密集型任务,最好的方式就是一个线程处理所有任务, ########cpython如何提高效率 在cpthon中有GIL锁导致多线程不能并行执行,丧失了多核优势,即使开启了多线程,也只能并发, 这个时候完全可以使用协程来实现并发,优点:不会占用更多的无用资源 缺点:如果是计算任务,使用协程反而降低效率 在cpython中要想效率最高,多进程+单线程+协程.如果这个都不行,只能集群分布式了. 终极杀招:对IO密集型任务     在系统中可承受的范围内,开启多进程     在进程下开启多个协程任务   def task1():     print("taks1 run")     #gevent.sleep(3)     #需要加猴子补丁,去检测IO     print("task1 over")   def task1():     print("taks2 run")     print("task2 over")   g1 = gevent.spawn(task1) g2 = gevent.spawn(task2)   gevent.joinall([g1,g2])     使用spawn来创建一个协程任务,想要任务执行,必须保证主线程没挂,因为所有的协程任务都是主线程在执行,必须调用join来等待协程任务,理论上等待执行时间最长的任务就行,但是不清楚谁的时间长,所以,可以全部等   gevent不具备检测IO的能力,需要用猴子为他打补丁,打补丁之后就能检测IO(需要写到最上面去,必须保证导入模块前,就打完补丁) 使用场景:cpython下IO密集型任务,对于本来就可以利用多核优势的场景下,这个就没必要开协程了   猴子补丁 就是把 原本阻塞的代码换成非阻塞的代码                            

标签:协程,day38,res,并发,任务,线程,IO
来源: https://www.cnblogs.com/yclzp/p/10985781.html