线程池、进程池、回调函数(add_done_callback)、map
2021/7/2 7:21:17
本文主要是介绍线程池、进程池、回调函数(add_done_callback)、map,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
池concurrent.futrues
- 什么是池?
- 要在程序开始的时候,还没提交任务,先创建几个线程或者进程放在一个池子里,这就是池
- 为什么要用池?
- 如果先开好进程/或线程,那么有任务之后就可以直接使用这个池中的数据了
- 开好的进程或线程会一直存在池中,可以被多个任务反复利用,这样极大的减少了开启,关闭,调度线程、进程的时间开销
- 池中的进程/线程个数控制了操作系统需要调度的任务个数,控制池中的单位,有利于提高操作系统的效率, 减轻操作系统的负担
线程池
-
线程池里面推荐的线程个数(一般根据IO的比例定制):cpu_count
*
5 -
代码:
-
from threading import current_thread from concurrent.futures import ThreadPoolExecutor import time import random def func(): print(current_thread().ident,'start') #从内部获取开启进程的个数 time.sleep(random.randint(1,4)) print(current_thread().ident, 'end') tp=ThreadPoolExecutor(4) #起了4个线程 for i in range(10): tp.submit(func) #submit向池中提交任务 #得: 6876 start 13340 start 11760 start 6080 start 6876 end 6876 start 6080 end 6080 start 11760 end 11760 start 6876 end 6876 start 13340 end 13340 start 11760 end 11760 start 11760 end 6080 end
-
带参数
-
from threading import current_thread from concurrent.futures import ThreadPoolExecutor import time import random def func(a,b): print(current_thread().ident,'start',a,b) #从内部获取开启进程的个数 time.sleep(random.randint(1,4)) print(current_thread().ident, 'end') tp=ThreadPoolExecutor(4) #起了4个线程 for i in range(10): tp.submit(func,i,i+1) #得: 8624 start 0 1 7884 start 1 2 7844 start 2 3 11832 start 3 4 7844 end 7844 start 4 5 8624 end 8624 start 5 6 7884 end 7884 start 6 7 11832 end 11832 start 7 8 7844 end 7844 start 8 9 7884 end 7884 start 9 10 11832 end 8624 end 7884 end 7844 end
-
进程池
-
运用场景:高计算的时候,没有io(没有文件操作,没有数据库操作,没有网络操作,没有input)
-
进程池里面推荐的进程个数:cpu_count
*
1<进程个数<cpu_count*
2 -
代码:
-
import os from concurrent.futures import ProcessPoolExecutor import time import random def func(a, b): print(os.getpid(), 'start', a, b) # 从内部获取开启进程的个数 time.sleep(random.randint(1, 4)) print(os.getpid(), 'end') if __name__ == '__main__': tp = ProcessPoolExecutor(4) # 起了4个线程 for i in range(10): tp.submit(func, i, i + 1) #得 7836 start 0 1 8888 start 1 2 11916 start 2 3 14660 start 3 4 11916 end 11916 start 4 5 7836 end 7836 start 5 6 14660 end 14660 start 6 7 7836 end 8888 end 7836 start 7 8 8888 start 8 9 14660 end 14660 start 9 10 11916 end 7836 end 8888 end 14660 end
-
获取任务结果
from concurrent.futures import ProcessPoolExecutor def func(a, b): return a*b if __name__ == '__main__': tp = ProcessPoolExecutor(4) # 起了4个线程 future_l={} for i in range(10): #异步非阻塞 ret=tp.submit(func, i, i + 1) future_l[i]=ret # print(ret) #Future未来对象 # print(ret.result()) #缺点:慢,效率低 for key in future_l: #同步阻塞 print(key,future_l[key].result())
-
回调函数(add_done_callback)
-
回调函数(异步阻塞),给ret对象绑定一个回调函数。等ret对应的任务有了结果之后,立即调用print_func这个函数,就可以 立即对函数进行处理,而不是按照顺序接受结果,处理结果
-
代码
-
from concurrent.futures import ProcessPoolExecutor import os import time import random def func(a, b): print(os.getpid(), 'start', a, b) # 从内部获取开启进程的个数 time.sleep(random.randint(1, 4)) print(os.getpid(), 'end') return a*b def print_func(ret): print(ret.result()) if __name__ == '__main__': tp = ProcessPoolExecutor(4) # 起了4个线程 for i in range(10): #异步非阻塞 ret=tp.submit(func, i, i + 1) ret.add_done_callback(print_func) #异步阻塞,回调函数,给ret对象绑定一个回调函数。 # 等ret对应的任务有了结果之后,立即调用print_func这个函数 #就可以立即对函数进行处理,而不是按照顺序接受结果,处理结果 #得: 15284 start 0 1 7540 start 1 2 544 start 2 3 6880 start 3 4 7540 end 7540 start 4 5 2 15284 end 544 end 544 start 5 6 6 15284 start 6 7 0 6880 end 6880 start 7 8 12 15284 end 15284 start 8 9 42 7540 end 7540 start 9 10 20 544 end 30 7540 end 90 15284 end 6880 end 72 56
-
map
- map函数只适合传递简单的参数,并且必须是一个可迭代的数据类型作为参数
from concurrent.futures import ProcessPoolExecutor def func(a): b=a+1 return a*b if __name__ == '__main__': tp = ProcessPoolExecutor(4) # 起了4个线程 tm=tp.map(func,range(20)) #使用map将一个可迭代对象的元素依次传入函数 print(list(tm)) #得: [0, 2, 6, 12, 20, 30, 42, 56, 72, 90, 110, 132, 156, 182, 210, 240, 272, 306, 342, 380]
这篇关于线程池、进程池、回调函数(add_done_callback)、map的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-25【机器学习(二)】分类和回归任务-决策树(Decision Tree,DT)算法-Sentosa_DSML社区版
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享