记忆碎片之python线程池、submit()、done()、result()、wait()、as_completed()、map()方法

2023-11-07

大量注释,小白一看就懂的多线程及参数使用

threadpool已经不再是主流,但是对于任务数量不断增加的程序,每有一个任务就生成一个线程,最终会导致线程数量的失控,例如,整站爬虫,假设初始只有一个链接a,那么,这个时候只启动一个线程,运行之后,得到这个链接对应页面上的b,c,d,,,等等新的链接,作为新任务,这个时候,就要为这些新的链接生成新的线程,线程数量暴涨。在之后的运行中,线程数量还会不停的增加,完全无法控制。所以,对于任务数量不端增加的程序,固定线程数量的线程池是必要的。
相比threading,该模块通过submit返回的是一个future对象,它是一个未来可期的对象
通过它可以获悉线程的状态,主线程或者主进程中可以获取某一个线程或进程执行的状态或者某一个任务执行的状态及返回值
主线程可以获取某一个线程或者任务的状态,以及返回值
当一个线程完成的时候,主线程能够立即知晓
让多线程和多进程的编码接口一致

from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
import time


def spider(page):
    time.sleep(page)
    print(f"crawl task {page} finished")
    return page


# with ThreadPoolExecutor(max_workers=5) as t:  # 创建一个最大容纳量为5的线程池
#     task1 = t.submit(spider, 1)
#     task2 = t.submit(spider, 2)  # 通过submit提交执行的函数到线程池中
#     task3 = t.submit(spider, 3)
#
#     # 通过done来判断线程是否完成
#     print(f"task1: {task1.done()}")
#     print(f"task2: {task2.done()}")
#     print(f"task3: {task3.done()}")
#
#     time.sleep(2.5)
#
#     print(f"task1: {task1.done()}")
#     print(f"task2: {task2.done()}")
#     print(f"task3: {task3.done()}")
#     # 通过result()来获取返回值
#     print(task1.result())

# 使用with语句,通过ThreadPoolExecutor构造实例,
# 同时传入max_workers参数来设置线程池中最多能同时运行的线程数目

# 使用submit函数来提交线程需要执行的任务到线程池中,并返回该任务的句柄(类似文件、画图),
# 注意submit()不是阻塞的,而是立即返回的

# 通过使用done()方法判断该任务是否结束,提交任务后立即判断任务状态,显示都是未完成,在显示2.5秒后
# task1和task2执行完毕,task3仍然在执行中

# 使用result()方法可以获取任务的返回值

# 方法和参数
# wait(fs, timeout=None, return_when=All_COMPLETED)
# fs 表示需要执行的序列
# timeout 等待的最大时间,如果超过这个时间
# return_when 表示wait返回结果的结果,默认为ALLP_COMPLETED全部执行完成后再返回结果

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


def spider2(page):
    time.sleep(page)
    print(f"crawl task {page} finished")
    return page


# with ThreadPoolExecutor(max_workers=5) as t:
#     all_task = [t.submit(spider2, page) for page in range(1, 5)]
#     # 返回条件 FIRST_COMPLETED 当第一个任务完成的时候就停止等待,继续主线程任务,所以紧接着打印了“结束”
#     wait(all_task, return_when=FIRST_COMPLETED)
#     print("结束")
#     # 设置延时(等待)时间2.5秒
#     print(wait(all_task, timeout=2.5))
#     # 所以最后只有task4还在运行

# as_completed
# 虽然使用return_when=FIRST_COMPLETED判断任务是否结束,但是不能在主线程中一直判断
# 最好的办法是当某个任务结束来,就给主线程返回结果,而不是一直判断每个任务是否结束
# as_completed就是当子线程中的任务执行完成后,直接用result()获取返回结果

from concurrent.futures import as_completed


def spider3(page):
    time.sleep(page)
    print(f"crawl task {page} finished")
    return page


def main():
    with ThreadPoolExecutor(max_workers=5) as t:
        obj_list = []
        for page in range(1, 5):
            obj = t.submit(spider3, page)
            obj_list.append(obj)
        for future in as_completed(obj_list):
            data = future.result()
            print(f"main:{data}")


# main()    使用过后发现,这个多线程比上面的测试耗时都多一些
# as_completed()方法是一个生成器,在没有任务完成的时候就会一直阻塞,除非设置了timeout
# 当某个任务完成的时候,会yield这个任务,就能执行for循环下面的语句,然后继续阻塞程序,直到所有任务结束
# 同时,先完成的任务会先返回给主线程

# map
# map(fn, *iterables, timeout=None)
# fn 需要线程执行的函数
# iterables 接收一个可迭代对象
# 和wait()的timeout一样,用于延时,但是map是返回线程执行的结果,如果timeout小于线程执行时间会抛出TimeoutError

def spider4(page):
    time.sleep(page)
    print(f"crawl task {page} finished")
    return page


def main2():
    executor = ThreadPoolExecutor(max_workers=4)
    i = 1
    # 列表中的每一个元素都执行来spider4()函数,并分配各线程池   task1:2
    for result in executor.map(spider4, [2, 3, 1, 4]):
        print(f"task{i}:{result}")
        i += 1


main2()
# 使用map方法,无需提前使用submit方法,与Python高阶函数map含义相同,都是将序列中的每个元素都执行同一个行数
# 与as_completed()方法的结果不同,输出顺序和列表的顺序相同,
# 就算1秒的任务执行完成,也会先打印前面提交的任务返回的结果

# map可以保证输出的顺序, submit输出的顺序是乱的
# 如果你要提交的任务的函数是一样的,就可以简化成map。但是假如提交的任务函数是不一样的,
# 或者执行的过程之可能出现异常(使用map执行过程中发现问题会直接抛出错误)就要用到submit()
# submit和map的参数是不同的,submit每次都需要提交一个目标函数和对应的参数,
# map只需要提交一次目标函数,目标函数的参数放在一个迭代器(列表,字典)里就可以。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

记忆碎片之python线程池、submit()、done()、result()、wait()、as_completed()、map()方法 的相关文章

随机推荐

  • Latex: 参考文献双栏对齐

    参考 How to level columns in bibliography Latex 参考文献双栏对齐 需要实现的效果 方法1 在开头引用balance usepackage balance 在文末 参考文献前 加上 balance
  • Stream使用技巧(1)------数据处理技巧

    Stream使用技巧 1 数据处理技巧 一 背景 作为java8新特性之一的Stream API为开发者带来了极大的便利 它可以对我们需要操作的集合进行非常复杂的操作 以活的我们想要的结果 本文不会告诉你什么是Stream 毕竟网上花里胡哨
  • 双口ram 简介及Verilog实现

    简介 RAM Random Access Memory 随机存储器 是一种用来暂时存储中间数据的存储器 掉电易失 按照类型可以分为单口ram 双口ram 其中双口ram又有简单 伪 的ram 真双端口ram 在异步FIFO的内部就是一个双端
  • Networdx小案例学习

    文章目录 图的类型 无向图小案例 有向图的小案例 参考资料 图的类型 无向图小案例 import networkx as nx import matplotlib pyplot as plt G nx DiGraph 0 1 1 2 2 3
  • couldn‘t find package required on the “npm“ registry

    切换npm源就行 nrm use taobao
  • 对Attention is all you need 的理解

    本文参考的原始论文地址 https arxiv org abs 1706 03762 谷歌昨天在arxiv发了一篇论文名字教Attention Is All You Need 提出了一个只基于attention的结构来处理序列模型相关的问题
  • 遗传算法与C++实现

    1 遗传算法 核心是达尔文优胜劣汰适者生存的进化理论的思想 一个种群 通过长时间的繁衍 种群的基因会向着更适应环境的趋势进化 适应性强的个体基因被保留 后代越来越多 适应能力低个体的基因被淘汰 后代越来越少 经过几代的繁衍进化 留下来的少数
  • c++ vector

    初始化 1 默认初始化 vector为空 size为0 表明容器中没有元素 而且 capacity 也返回 0 意味着还没有分配内存空间 这种初始化方式适用于元素个数未知 需要在程序中动态添加的情况 vector
  • 华为OD机试 Python 【最小循环子数组】

    描述 给定一个数字数组 看看这个数组能否由一个子数组不断重复形成的 请找出那个可能的最小子数组 输入方式 第一行 数组里的数字数量 记作 n 1 n 100000 第二行 数组的数字 用空格隔开 每个数字都在 0 到 9 之间 输出方式 打
  • Pandas Excel Writer writer.book = book的原因

    工作 from openpyxl import load workbook import pandas as pd file r YOUR PATH TO EXCEL HERE df1 pd DataFrame Data 10 20 30
  • having子句与where子句

    1 相同点 都是对记录进行筛选 2 不同点 2 1 where 不能放在group by后面 2 2 having 是跟group by连在一起用的 放在group by 后面 此时的作用相当于where 2 3 where 后面的条件中不
  • 基于Python招聘爬虫可视化-招聘数据可视化

    视频展示 基于Python招聘爬虫可视化 项目定制 招聘数据可视化 哔哩哔哩 bilibili
  • C++primer练习12.1.4

    12 14 struct destination 连接的目的地 struct connection 使用连接所需的信息 connection connect destination 打开连接 void disconnect connecti
  • Ext智能提示 - Eclipse 3.2

    Eclipse的Ext 2 0 2智能提示 它提供了非常准确的Ext API提示 如图 下载地址 http www agpad com downloads spket 1 6 12 zip 引用方法 方法來自會員 kittig 1 将下载回
  • 【模拟电路】二极管分类

    1 TVS二极管 瞬态电压抑制器 在电路中 TVS二极管都是反向接在电源端 一旦瞬时电压超过电路正常工作电压后 TVS二极管便发生雪崩效应 提供给瞬时电流一个超低电阻通路 从而使得被保护器件或设备避免受到损毁 图1 图2 找了个网上的图 先
  • 必看!区块链如何推动电商行业的发展?

    区块链技术被认为是第四次工业革命中最具颠覆性的创新技术 世界上还没有见过比区块链技术更强大的技术 它可能会对所有经济部门产生潜在的影响 给它们带来一流的效率 近些年来 区块链技术在金融服务行业 能源行业 物流行业 供应链管理行业 医疗行业等
  • ambari自动化Hadoop部署

    20200922 0 引言 几年前为了处理大量的日志 简单学习了hadoop的内容 之后就在自己的几台破PC上进行了实验 当时安装的方式步骤大致如下 利用expect脚本完成免密登陆 利用clush进行集群管理 比如传输文件 或者文件及命令
  • 软件测试风险清单

    软件测试风险 主要分为 风险评估和风险控制 软件测试风险大致可以从以下几个方面考虑 一 人力 风险评估点 1 人力资源不够 2 测试用例未被完全执行 3 人员流动 测试人员对业务不熟悉 相对应的风险控制 1 按照项目计划 测试计划准备好测试
  • Altium Designer 16 放置PCB禁止布线层步骤

    放置PCB禁止布线层步骤 菜单栏中的Place gt 子菜单项Keepout gt 有几种设置模式一般选用Track 直线绘制 添加以后绘制线图不能超过禁止布线层所圈出的范围
  • 记忆碎片之python线程池、submit()、done()、result()、wait()、as_completed()、map()方法

    大量注释 小白一看就懂的多线程及参数使用 threadpool已经不再是主流 但是对于任务数量不断增加的程序 每有一个任务就生成一个线程 最终会导致线程数量的失控 例如 整站爬虫 假设初始只有一个链接a 那么 这个时候只启动一个线程 运行之