6. 线程池
线程不是开的越多越好,开的多了可能会导致系统的性能下降,甚至崩溃。线程池可以控制线程的最大并发数,避免线程过多带来的问题。
使用线程池
python
import time
from concurrent.futures import ThreadPoolExecutor
def task(video_url, num):
print(f"开始下载视频 {num}:{video_url}")
time.sleep(2) # 模拟下载时间
print(f"视频 {num} 下载完成")
# 创建线程池,最多维护10个线程
pool = ThreadPoolExecutor(max_workers=10)
url_list = ["www.xxx={}.com".format(i) for i in range(300)]
for url in url_list:
# 在线程池中提交一个任务,线程池中如果有空闲线程,则分配一个线程去执行,执行完毕后再将线程交给线程池;如果没有空闲线程,则等待有空闲线程后再执行。
pool.submit(task, url, 2)
# 主线程等待线程池中的所有任务执行完毕
print("主线程执行完毕")shutdown()
shutdown() —— 主线程在此等候所有线程执行完毕。
python
import time
from concurrent.futures import ThreadPoolExecutor
def task(video_url, num):
print(f"开始下载视频 {num}:{video_url}")
time.sleep(2) # 模拟下载时间
print(f"视频 {num} 下载完成")
# 创建线程池,最多维护10个线程
pool = ThreadPoolExecutor(max_workers=10)
url_list = ["www.xxx={}.com".format(i) for i in range(300)]
for url in url_list:
# 在线程池中提交一个任务,线程池中如果有空闲线程,则分配一个线程去执行,执行完毕后再将线程交给线程池;如果没有空闲线程,则等待有空闲线程后再执行。
pool.submit(task, url, 2)
print("执行中")
pool.shutdown() # 主线程在此等候所有线程执行完毕
print("继续往下走")任务回调
python
# 可以做分工,例如task专门下载,done专门将下载的数据写入本地文件
import time
from concurrent.futures import ThreadPoolExecutor, Future
def task(video_url, num):
print("开始执行任务", video_url)
time.sleep(2)
return random.randint(1, 100)
def done(response):
print("任务执行后的返回值", response.result())
# 创建线程池,最多维护10个线程
pool = ThreadPoolExecutor(max_workers=10)
url_list = ["www.xxx={}.com".format(i) for i in range(30)]
for url in url_list:
# 将任务交给线程池会返回一个特殊的对象。他跟 task 是 1:1 的关系。
future = pool.submit(task, url, 2)
# 回调 task 的尾部自动多跑几行回调代码(仍在同一个工作线程里),不是再提交一个任务。
future.add_done_callback(done)