进程线程和协程二

前言

上面那篇文章我们提到了线程和锁的一些概念,但是代码有些冗余,比如需要我手动执行start,手动执行join,子线程数量少还好,如果多起来的话,就会显得代码很呆,因此引出下一个概念-->线程池(ThreadPoolExecutor)

线程池-submit版本

示例代码

python 复制代码
from concurrent.futures import ThreadPoolExecutor
from threading import Thread, Lock
import time

total_money = 200

l = Lock()

def speed_money(name: str, sp_money: int):
    time.sleep(1)
    with l:
        global total_money
        print(f"\n当前线程是{name},准备取{sp_money}元,开始检测余额是否充足")
        if total_money:
            time.sleep(1)  # 只是增加了这步
            print(f"\n当前线程是{name},余额充足为{total_money},开始取钱")
            total_money = round(total_money - sp_money, 2)
            print(f"\n当前线程是{name},已经取了{sp_money},账号余额{total_money}")
    return total_money

def main():
    # 构建线程
    with ThreadPoolExecutor() as executor:
        e1 = executor.submit(speed_money, "第一个线程", 100)
        e2 = executor.submit(speed_money, "第二个线程", 100)
        e3 = executor.submit(speed_money, "第三个线程", 100)

    print("\ne1,e2,e3都submit了~~~~~")
    print("\n开始依次获取执行结果")
    print(e1.result())
    print(e2.result())
    print(e3.result())
    print("\ne1,e2,e3都result完了,")

if __name__ == '__main__':
    start_time = time.time()
    main()
    print("\nmain函数执行结束")
    end_time = time.time()
    print("\n总耗时", round(end_time - start_time, 2))

执行结果

我们可以看到 在submit的时候,3个子线程就依次启动了,并且是没有阻塞主线程的,然后在子线程获取result的发现主线程是又被阻塞的 因此得出

结论

  • 线程池submit和线程Thread的start很像(ps都是启动子线程,并且不会阻塞主线程)
  • 线程池result和线程Thread的join很像(ps都是阻塞主线程,直到子线程执行完)
  • 不同点是result是会获取子线程的结果的,但是join不行

线程池-map版本

示例代码

python 复制代码
from concurrent.futures import ThreadPoolExecutor
from threading import Thread, Lock
import time

total_money = 200

l = Lock()

def speed_money(name: str, sp_money: int):
    time.sleep(1)
    with l:
        global total_money
        print(f"\n当前线程是{name},准备取{sp_money}元,开始检测余额是否充足")
        if total_money:
            time.sleep(1)  # 只是增加了这步
            print(f"\n当前线程是{name},余额充足为{total_money},开始取钱")
            total_money = round(total_money - sp_money, 2)
            print(f"\n当前线程是{name},已经取了{sp_money},账号余额{total_money}")
    return total_money

def main():
    # 构建线程
    with ThreadPoolExecutor() as executor:
        results = executor.map(
            speed_money,
            ["第一个线程", "第二个线程", "第三个线程"],  # speed_money接受的传入第一个参数的可迭代对象
            [100, 100, 100]  # speed_money接受的传入第二个参数的可迭代对象
        )

    print("\ne1,e2,e3开始map了~~~~~")
    print("\n开始依次获取执行结果")
    for result in results:
        print("\n result", result)

    print("\ne1,e2,e3都map完了,")

if __name__ == '__main__':
    start_time = time.time()
    main()
    print("\nmain函数执行结束")
    end_time = time.time()
    print("\n总耗时", round(end_time - start_time, 2))

执行结果

通过结果可以发现,基本上和submit打印的都是一样的,所以说数据也是没问题的,但是相较于submit的话,map就很通用了,使用方式和普通的map保持一致,也是在map的时候子线程就会执行,执行完得到的是一个可迭代对象,需要使用for或者next来获取子线程的返回值

map和submit的区别

相关推荐
henujolly2 小时前
go学习day two
后端
AI袋鼠帝2 小时前
腾讯这只小程序Agent🦀,帮我找到了最强日程、文件、知识管理姿势
后端
努力的小郑2 小时前
突发!Claude Code 51万行源码全网裸奔:一场史诗级“开源”事故,国内大厂笑麻了
前端·后端·ai编程
HashTang3 小时前
Claude Code 源码中 REPL.tsx 深度解析:一个 5005 行 React 组件的架构启示
前端·后端·ai编程
thatway19893 小时前
ARM TFM-1介绍及代码下载运行适配
后端
千寻girling4 小时前
不知道 Java 全栈 + AI 编程有没有搞头 ?
前端·人工智能·后端
小码哥_常4 小时前
Spring Boot 实现网络限速:让流量“收放自如”
后端
johnrui5 小时前
SpringBoot-JdbcTemplate
java·spring boot·后端
Victor3566 小时前
MongoDB(72)如何创建用户和角色?
后端
Victor3566 小时前
MongoDB(71)如何启用MongoDB身份验证?
后端