3.2版本引入的模块.
异步并行任务编程模块, 提供一个高级的一部可执行的便利接口.
提供两个池执行器
ThreadPoolExecutor
异步调用的线程池的Executor
ProcessPlloExecutor
异步调用进程池的Executor
这两个池是惰性的, 不会立即创建线/进程
首先需要定义一个池额执行器对象, Executor类子类对象
方法 | 含义 |
---|---|
ThreadPoolExecutor (max_workers=1) |
池中至多创建max_workers个线程的池来同时异步执行,返回Executor实例 |
submit (fn, *args, **kwargs) |
提交执行的函数及其参数, 返回Future类的实例 |
shutdown (wait=True) |
清理池 |
Future类
方法 | 含义 |
---|---|
done() |
如果调用被成功的取消或者执行完成, 返回True (即线/进程已经结束了) |
cancelled () |
如果调用被成功的取消, 返回True |
running() |
如果正在运行且不能被取消, 返回True |
cancel() |
尝试取消调用.如果已经执行且不能取消返回False, 否则返回True |
result (timeout=None) |
取返回的结果, timeout为None, 一直等待返回; timeout设置到期,抛出concurrent.futures.TimeoutError异常(会阻塞) |
exception(timeout=None) | 取返回的异常, timeout为None, 一直等待返回;timeout设置到期, 抛出concurrent.futures.TimeoutError异常 |
import threading
from concurrent import futures
import logging
import time
# 定义输出的格式
FORMAT = "%(asctime)-15s\t[%(processName)s:%(threadName)s , %(process)d:%(thread)8d] %(message)s"
logging.basicConfig(level=logging.INFO, format=FORMAT)
def worker(n):
logging.info("begin to work{}".format(n))
time.sleep(5)
logging.info("finished{}".format(n))
# 创建线程池, 容量为3
executer = futures.ThreadPoolExecutor(max_workers=3)
fs = []
for i in range(3):
future = executer.submit(worker, i)
fs.append(future)
# for i in range(3, 6):
# future = executer.submit(worker, i)
# fs.append(future)
while True:
time.sleep(2)
logging.info(threading.enumerate()) ##输出正在运行的线程
flag = True
for f in fs: #判断是否还有未完成的任务
logging.info(f.done())
flag = flag and f.done() #有一个未完成flag都会变成False
if not flag:##出现一次就说明未完成, 提前结束
break
print("-" * 30)
if flag:
executer.shutdown()
logging.info(threading.enumerate())
break
## 线程一旦创建就不应该频繁被清除
方法一样. 就是使用多进程完成
import threading
from concurrent import futures
import logging
import time
# 定义输出的格式
FORMAT = "%(asctime)-15s\t[%(processName)s:%(threadName)s , %(process)d:%(thread)8d] %(message)s"
logging.basicConfig(level=logging.INFO, format=FORMAT)
def worker(n):
logging.info("begin to work{}".format(n))
time.sleep(5)
logging.info("finished{}".format(n))
# 创建线程池, 容量为3
if __name__=='__main__':
executer = futures.ProcessPoolExecutor(max_workers=3)
fs = []
for i in range(3):
future = executer.submit(worker, i)
fs.append(future)
# for i in range(3, 6):
# future = executer.submit(worker, i)
# fs.append(future)
while True:
time.sleep(2)
logging.info(threading.enumerate()) ##输出正在运行的线程
flag = True
for f in fs: #判断是否还有未完成的任务
logging.info(f.done())
flag = flag and f.done() #有一个未完成flag都会变成False
if not flag:##出现一次就说明未完成, 提前结束
break
print("-" * 30)
if flag:
executer.shutdown()
logging.info(threading.enumerate())
break
和ThreadingPoolExecutor一样, 只是需要加上一句if __name__=="__main__":
concurrent.futures.ProcessPoolExecutor继承自confurrent.futures._base.Executor,而父类有__enter__和__exit__方法,支持上下管理,可以使用with语句.
__exit__方法本质还是调用shutdown()wait=True), 就是一直阻塞到所有运行的任务完成.
使用方法
from concurrent import futures
with futures.ThreadPoolExecutor(max_workers=1) as executor:
future = executor.submit(pow, 2, 3)
print(future.result()) ##阻塞,等待返回结果
# futures.ThreadPoolExecutor.__enter__()
# def __enter__(self):
# return self
#
# def __exit__(self, exc_type, exc_val, exc_tb):
# self.shutdown(wait=True)
# return False
改造之前的例子
import threading
from concurrent import futures
import logging
import time
#定义输出的格式
FORMAT = "%(asctime)-15s\t[%(processName)s:%(threadName)s , %(process)d:%(thread)8d] %(message)s"
logging.basicConfig(level=logging.INFO, format=FORMAT)
def worker(n):
logging.info("begin to work{}".format(n))
time.sleep(5)
logging.info("finished{}".format(n))
# 创建线程池, 容量为3
if __name__=='__main__':
fs = []
with futures.ProcessPoolExecutor(max_workers=3) as executer:
for i in range(3):
future = executer.submit(worker, i)
fs.append(future)
# for i in range(3, 6):
# future = executer.submit(worker, i)
# fs.append(future)
while True:
time.sleep(2)
logging.info(threading.enumerate()) ##输出正在运行的线程
flag = True
for f in fs: #判断是否还有未完成的任务
logging.info(f.done())
flag = flag and f.done() #有一个未完成flag都会变成False
if not flag:##出现一次就说明未完成, 提前结束
break
print("-" * 30)
if flag:
logging.info(threading.enumerate())
break
该库统一了线程池,进程池调用,简化了编程.
是Python简单的思想哲学的体现.
唯一的缺点:无法设置线程名称. 但是这都不值一提.