线程池

2020-11-27  本文已影响0人  拖延症旳理想主义者

模拟网页下载的任务

def get_page_html(seconds, url):
    # sleep模拟下载耗时
    time.sleep(seconds)
    logger.info(f"URL:{url}下载网页成功,耗时{seconds}秒")
    # 返回页面源码+耗时
    return url, seconds

实例化线程池,并提交下载任务

from concurrent.futures import ThreadPoolExecutor

# 实例化线程池,并指定线程池的容量
executor = ThreadPoolExecutor(max_workers=1)

# submit方法:向线程池中提交任务:函数名+参数列表
task_1 = executor.submit(get_page_html, 3, "http://3.com")
task_2 = executor.submit(get_page_html, 2, "http://2.com")

任务执行完成后,返回一个Future对象

# 未来对象,或者是任务执行结果的容器
class Future(object):
    """Represents the result of an asynchronous computation."""

Future对象里的常用方法

1、获取线程的执行状态

# 获取线程任务的执行状态
logger.info(f"task_1是否执行完毕: {task_1.done()}")
logger.info(f"task_2是否执行完毕: {task_2.done()}")

2、获取线程任务的执行结果

# 获取线程异步执行完成后的结果,这里会阻塞主线程,等待子线程的执行结果
logger.info(task_1.result())

result()是一个阻塞的方法

3、取消线程任务的执行

# 在线程未开启前,即没有进到线程池中前,可以关闭该线程任务
task_2.cancel()

4、添加回调函数

# 线程任务执行完成,可以指定回调函数,接受一个future作为参数
def callback(future):
    logger.info(future.result())
# 添加回调函数
task_1.add_done_callback(callback)

批量提交线程任务

# 实例化线程池对象
executor = ThreadPoolExecutor(max_workers=3)

# 使用列表生成器批量提交任务到线程池
all_task = [executor.submit(get_page_html, seconds, url) for seconds, url in [(1, "http://1"), (2, "http://2")]]

线程任务执行完毕后立即接收返回值

from concurrent.futures import ThreadPoolExecutor, as_completed, wait, ALL_COMPLETED

# as_completed是一个生成器,会把执行完成的Future yield回来
for future in as_completed(fs=all_task):
    logger.info(future.result())

等待线程任务全部执行完毕

# 主线程阻塞,等待所有子线程执行完毕
wait(all_task, return_when=ALL_COMPLETED)
logger.info("主线程执行完毕")

使用线程池执行Selenium程序

# _*_coding:utf-8_*_

"""
@Time   : 2020/11/27 10:10
@Author : CarpLi
@File   : thread_pool_selenium.py
@Desc   : 使用线程池启动Chrome访问百度
"""
import time
from loguru import logger
from concurrent.futures import ThreadPoolExecutor, as_completed
from selenium.webdriver import Chrome


# chrome浏览器访问url
def open_url_page(url):
    chrome = Chrome()
    chrome.get(url)
    time.sleep(2)
    title = chrome.title
    chrome.quit()
    return title


executor = ThreadPoolExecutor(max_workers=5)
all_task = [executor.submit(open_url_page, f"https://www.baidu.com/s?wd={url}") for url in range(1, 20)]

for future in as_completed(all_task):
    # 有线程任务执行成功就直接返回
    logger.info(future.result())


if __name__ == '__main__':
    pass

上一篇 下一篇

猜你喜欢

热点阅读