python线程池ThreadPoolExecutor与进程池ProcessPoolExecutor
python中ThreadPoolExecutor(线程池)与ProcessPoolExecutor(进程池)都是concurrent.futures模块下的,主线程(或进程)中可以获取某一个线程(进程)执行的状态或者某一个任务执行的状态及返回值。
通过submit返回的是一个future对象,它是一个未来可期的对象,通过它可以获悉线程的状态
ThreadPoolExecutor(线程池)
通过submit函数提交执行的函数到线程池中,done()判断线程执行的状态:
import time
from concurrent.futures import ThreadPoolExecutor def get_thread_time(times):
time.sleep(times)
return times # 创建线程池 指定最大容纳数量为4
executor = ThreadPoolExecutor(max_workers=4)
# 通过submit提交执行的函数到线程池中
task1 = executor.submit(get_thread_time, (1))
task2 = executor.submit(get_thread_time, (2))
task3 = executor.submit(get_thread_time, (3))
task4 = executor.submit(get_thread_time, (4))
print("task1:{} ".format(task1.done()))
print("task2:{}".format(task2.done()))
print("task3:{} ".format(task3.done()))
print("task4:{}".format(task4.done()))
time.sleep(2.5)
print('after 2.5s {}'.format('-'*20)) done_map = {
"task1":task1.done(),
"task2":task2.done(),
"task3":task3.done(),
"task4":task4.done()
}
# 2.5秒之后,线程的执行状态
for task_name,done in done_map.items():
if done:
print("{}:completed".format(task_name))
result:
task1:False
task2:False
task3:False
task4:False
after 2.5s --------------------
task1:completed
task2:completed
初始状态4个task都是未完成状态,2.5秒后task1和task2执行完成,task3和task由于是sleep(3) sleep(4)所以仍然是未完成的sleep状态
通过wait()判断线程执行的状态:
wait(fs, timeout=None, return_when=ALL_COMPLETED),wait接受3个参数,fs表示执行的task序列;timeout表示等待的最长时间,超过这个时间即使线程未执行完成也将返回;return_when表示wait返回结果的条件,默认为ALL_COMPLETED全部执行完成再返回:
import time
from concurrent.futures import (
ThreadPoolExecutor, wait
) def get_thread_time(times):
time.sleep(times)
return times start = time.time()
executor = ThreadPoolExecutor(max_workers=4)
task_list = [executor.submit(get_thread_time, times) for times in [1, 2, 3, 4]]
i = 1
for task in task_list:
print("task{}:{}".format(i, task))
i += 1
print(wait(task_list, timeout=2.5))
wait在2.5秒后返回线程的状态,result:
task1:<Future at 0x7ff3c885f208 state=running>
task2:<Future at 0x7ff3c885fb00 state=running>
task3:<Future at 0x7ff3c764b2b0 state=running>
task4:<Future at 0x7ff3c764b9b0 state=running>
DoneAndNotDoneFutures(
done={<Future at 0x7ff3c885f208 state=finished returned int>, <Future at 0x7ff3c885fb00 state=finished returned int>},
not_done={<Future at 0x7ff3c764b2b0 state=running>, <Future at 0x7ff3c764b9b0 state=running>})
可以看到在timeout 2.5时,task1和task2执行完毕,task3和task4仍在执行中
通过map返回线程的执行结果:
import time
from concurrent.futures import ThreadPoolExecutor def get_thread_time(times):
time.sleep(times)
return times start = time.time()
executor = ThreadPoolExecutor(max_workers=4) i = 1
for result in executor.map(get_thread_time,[2,3,1,4]):
print("task{}:{}".format(i, result))
i += 1
map(fn, *iterables, timeout=None),第一个参数fn是线程执行的函数;第二个参数接受一个可迭代对象;第三个参数timeout跟wait()的timeout一样,但由于map是返回线程执行的结果,如果timeout小于线程执行时间会抛异常TimeoutError。
import time
from concurrent.futures import ThreadPoolExecutor def get_thread_time(times):
time.sleep(times)
return times start = time.time()
executor = ThreadPoolExecutor(max_workers=4) i = 1
for result in executor.map(get_thread_time,[2,3,1,4]):
print("task{}:{}".format(i, result))
i += 1
map的返回是有序的,它会根据第二个参数的顺序返回执行的结果:
task1:2
task2:3
task3:1
task4:4
as_completed返回线程执行结果:
import time
from collections import OrderedDict
from concurrent.futures import (
ThreadPoolExecutor, as_completed
) def get_thread_time(times):
time.sleep(times)
return times start = time.time()
executor = ThreadPoolExecutor(max_workers=4)
task_list = [executor.submit(get_thread_time, times) for times in [2, 3, 1, 4]]
task_to_time = OrderedDict(zip(["task1", "task2", "task3", "task4"],[2, 3, 1, 4]))
task_map = OrderedDict(zip(task_list, ["task1", "task2", "task3", "task4"])) for result in as_completed(task_list):
task_name = task_map.get(result)
print("{}:{}".format(task_name,task_to_time.get(task_name)))
task1、task2、task3、task4的等待时间分别为2s、3s、1s、4s,通过as_completed返回执行完的线程结果,as_completed(fs, timeout=None)接受2个参数,第一个是执行的线程列表,第二个参数timeout与map的timeout一样,当timeout小于线程执行时间会抛异常TimeoutError。
task3:1
task1:2
task2:3
task4:4
通过执行结果可以看出,as_completed返回的顺序是线程执行结束的顺序,最先执行结束的线程最早返回。
ProcessPoolExecutor
对于频繁的cpu操作,由于GIL锁的原因,多个线程只能用一个cpu,这时多进程的执行效率要比多线程高。
线程池操作斐波拉切:
import time
from concurrent.futures import ThreadPoolExecutor def fib(n):
if n < 3:
return 1
return fib(n - 1) + fib(n - 2) start_time = time.time()
executor = ThreadPoolExecutor(max_workers=4)
task_list = [executor.submit(fib, n) for n in range(3, 35)]
thread_results = [task.result() for task in as_completed(task_list)]
print(thread_results)
print("ThreadPoolExecutor time is: {}".format(time.time() - start_time))
result:
[8, 5, 3, 2, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 10946, 46368, 6765, 28657, 17711, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887]
ThreadPoolExecutor time is: 4.998981237411499
进程池操作斐波拉切:
import time
from concurrent.futures import ProcessPoolExecutor def fib(n):
if n < 3:
return 1
return fib(n - 1) + fib(n - 2) start_time = time.time()
executor = ProcessPoolExecutor(max_workers=4)
task_list = [executor.submit(fib, n) for n in range(3, 35)]
process_results = [task.result() for task in as_completed(task_list)]
print(process_results)
print("ProcessPoolExecutor time is: {}".format(time.time() - start_time))
result:
[2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 75025, 28657, 46368, 196418, 121393, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887]
ProcessPoolExecutor time is: 3.3585257530212402
可以看出,对于频繁cpu操作进程是优于线程的,3.3s<4.9s
ProcessPoolExecutor在使用上和ThreadPoolExecutor大致是一样的,它们在futures中的方法也是相同的,但是对于map()方法ProcessPoolExecutor会多一个参数chunksize(ThreadPoolExecutor中这个参数没有任何作用),chunksize将迭代对象切成块,将其作为分开的任务提交给pool,对于很大的iterables,设置较大chunksize可以提高性能。
python线程池ThreadPoolExecutor与进程池ProcessPoolExecutor的更多相关文章
- GIL全局解释器锁、死锁现象、python多线程的用处、进程池与线程池理论
昨日内容回顾 僵尸进程与孤儿进程 # 僵尸进程: 所有的进程在运行结束之后并不会立刻销毁(父进程需要获取该进程的资源) # 孤儿进程: 子进程正常运行 但是产生该子进程的父进程意外死亡 # 守护进程: ...
- CIL锁,GIL与线程池的区别,进程池和线程池,同步与异步
一.GIL锁 什么是GIL? 全局解释器锁,是加在解释器上的互斥锁 GC是python自带的内存管理机制,GC的工作原理:python中的内存管理使用的是应用计数,每个数会被加上一个整型的计数器,表示 ...
- python 管道、数据共享、进程池
一.管道(Pipe)(了解) (详情参考:https://www.cnblogs.com/clschao/articles/9629392.html) 进程间通信(IPC)方式二:管道(不推荐使用,了 ...
- python 管道 事件(Event) 信号量 进程池(map/同步/异步)回调函数
####################总结######################## 管道:是进程间通信的第二种方式,但是不推荐使用,因为管道会导致数据不安全的情况出现 事件:当我运行主进程的 ...
- Python之网路编程之进程池及回调函数
一.数据共享 1.进程间的通信应该尽量避免共享数据的方式 2.进程间的数据是独立的,可以借助队列或管道实现通信,二者都是基于消息传递的. 虽然进程间数据独立,但可以用过Manager实现数据共享,事实 ...
- Python多进程库multiprocessing中进程池Pool类的使用[转]
from:http://blog.csdn.net/jinping_shi/article/details/52433867 Python多进程库multiprocessing中进程池Pool类的使用 ...
- python系列之 - 并发编程(进程池,线程池,协程)
需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ...
- Python标准模块--concurrent.futures(进程池,线程池)
python为我们提供的标准模块concurrent.futures里面有ThreadPoolExecutor(线程池)和ProcessPoolExecutor(进程池)两个模块. 在这个模块里他们俩 ...
- python 之 并发编程(进程池与线程池、同步异步阻塞非阻塞、线程queue)
9.11 进程池与线程池 池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务 池子内什么时候装进程:并发的任务属于计算密集型 池子内什么时候装线程:并发的任务属于I ...
随机推荐
- [PHP]flock文件IO锁的使用
一.flock概述 bool flock ( resource $handle , int $operation [, int &$wouldblock ] ) 参数 handle 文 ...
- LuoGu P1939 【模板】矩阵加速(数列)
板子传送门 矩阵快速幂学完当然要去搞一搞矩阵加速啦 (矩阵加速相对于矩阵快速幂来说就是多了一个构造矩阵的过程) 关于怎样来构造矩阵,这位大佬讲的很好呢 构造出矩阵之后,我们再去用矩阵快速幂乘出来,取[ ...
- Modbus库开发笔记之一:实现功能的基本设计
Modbus作为开放式的工业通讯协议,在各种工业设备中应用极其广泛.本人也使用Modbus通讯很多年了,或者用现成的,或者针对具体应用开发,一直以来都想要开发一个比较通用的协议栈能在后续的项目中复用, ...
- 使用 mod_rewrite 来修改 Confluence 6 的 URLs
备注:这个页面的文档是 Apache 的配置,而不是 Confluence 自己的配置.Atlassian 将会对 Confluence 的配置提供支持,但是我们不能保证能够对你所有在配置 Apach ...
- python之多线程通信
共享变量通信 事实上共享变量通信是会造成线程安全的,除非我们对这个共享变量是有足够了解的,如非必要就不要使用共享变量在线程间进行通信 Queue通信 理解不深入,暂不写
- 网络编程—udp
一.ip地址 1. 什么是地址 地址就是用来标记地点的 2. ip地址的作用 ip地址:用来在网络中标记一台电脑,比如192.168.1.1:在本地局域网上是唯一的. 3. ip地址的分类 每一个IP ...
- json数据转为Map集合
我是利用Gson来弄得Gson gson = new Gson();//显得出HashMap的类型Type type = new TypeToken<HashMap<String, Str ...
- jenkins+git+maven 增量部署思路以及相关脚本
之前通过jenkins+Git+maven这种方式打war包然后scp到测试环境使用,但是现在项目组要求打增量包,即只部署修改的文件和配置文件. 核心问题:如何获取到变动的文件??? 前置条件:初始化 ...
- java操作office和pdf文件java读取word,excel和pdf文档内容
在平常应用程序中,对office和pdf文档进行读取数据是比较常见的功能,尤其在很多web应用程序中.所以今天我们就简单来看一下Java对word.excel.pdf文件的读取.本篇博客只是讲解简单应 ...
- js cookie 工具
var CookieUtil = { get: function(name) { var cookieName = encodeURIComponent(name) + "=", ...