此外,使用线程池可以有效地控制系统中并发线程的数量。当系统中包含有大量的并发线程时,会导致系统性能急剧下降,甚至导致 Python 解释器崩溃,而线程池的最大线程数参数可以控制系统中并发线程的数量不超过此数。
线程池的使用
如果使用线程池/进程池来管理并发编程,那么只要将相应的 task 函数提交给线程池/进程池,剩下的事情就由线程池/进程池来搞定。
Exectuor 提供了如下常用方法:
Future 提供了如下方法:
cancel():取消该 Future 代表的线程任务。如果该任务正在执行,不可取消,则该方法返回
False;否则,程序会取消该任务,并返回 True。
cancelled():返回 Future 代表的线程任务是否被成功取消。
running():如果该 Future 代表的线程任务正在执行、不可被取消,该方法返回 True。
done():如果该 Funture 代表的线程任务被成功取消或执行完成,则该方法返回 True。
result(timeout=None):获取该 Future 代表的线程任务最后返回的结果。如果 Future
代表的线程任务还未完成,该方法将会阻塞当前线程,其中 timeout 参数指定最多阻塞多少秒。
exception(timeout=None):获取该 Future
代表的线程任务所引发的异常。如果该任务成功完成,没有异常,则该方法返回 None。
add_done_callback(fn):为该 Future 代表的线程任务注册一个“回调函数”,当该任务成功完成时,程序会自动触发该
fn 函数。
在用完一个线程池后,应该调用该线程池的 shutdown() 方法,该方法将启动线程池的关闭序列。调用 shutdown() 方法后的线程池不再接收新任务,但会将以前所有的已提交任务执行完成。当线程池中的所有任务都执行完成后,该线程池中的所有线程都会死亡。
使用线程池来执行线程任务的步骤如下:
线程池一些知识点:
from concurrent.futures import ThreadPoolExecutor
import requests
pool = ThreadPoolExecutor(10)
def task(url):
response = requests.get(url)
print(url,response)
url_list = (
"https://www.bing.com",
"https://www.shihu.com",
"https://www.sina.com",
"https://www.baidu.com",
"https://www.cnblogs.com",
"https://music.163.com/#"
)
for url in url_list:
pool.submit(task,url)
pool.shutdown(wait=True)
result
https://www.bing.com <Response [200]>
https://www.baidu.com <Response [200]>
https://www.cnblogs.com <Response [200]>
https://music.163.com/#
https://www.sina.com <Response [200]>
编写方法二:通过回调函数进行处理
from concurrent.futures import ThreadPoolExecutor
import requests
pool = ThreadPoolExecutor(10)
def task(url):
response = requests.get(url) #下载页面
return response
def done(future,*args,**kwargs):
response = future.result() #取得future对象进行操作
print(response.status_code,response.content)
url_list = (
"https://www.bing.com",
"https://www.jd.com",
"https://www.sina.com",
"https://www.baidu.com",
"https://www.cnblogs.com",
"https://music.163.com/#"
)
for url in url_list:
v = pool.submit(task,url) #获得一个返回值,其实就是访问url的响应
v.add_done_callback(done)