线程池和进程池

线程池和进程池

(1)简介

  • 在 Python 中,线程池(ThreadPoolExecutor)和进程池(ProcessPoolExecutor)是用于并发执行任务的两种机制。它们都可以有效地管理并发执行的任务,并且能够自动管理线程或进程的生命周期,从而简化了并发编程。

(1)线程池

  1. 基于线程的并发:线程池利用了线程的并发执行来加速任务的完成。Python 中的线程池通常使用标准库中的 concurrent.futures 模块来实现。

  2. 适用于 I/O 密集型任务:线程池适用于那些主要受限于 I/O 操作而不是 CPU 计算的任务,因为 Python 的全局解释器锁(GIL)会限制多线程情况下的并行计算。

  3. 示例代码

    import time
    from concurrent.futures import ThreadPoolExecutor
    def run(i):
    print(f'这是参数{i} 开始')
    time.sleep(1)
    print(f'这是参数{i} 结束')
    def main_thread():
    pool = ThreadPoolExecutor(5)
    for i in range(1,10):
    pool.submit(run, i)
    if __name__ == '__main__':
    main_thread()

(2)进程池

  1. 基于进程的并发:进程池使用多个进程来并行执行任务。每个进程都有自己的 Python 解释器和独立的内存空间,因此可以避免 GIL 的限制。

  2. 适用于 CPU 密集型任务:进程池适用于需要大量 CPU 计算的任务,因为它们可以充分利用多核 CPU 的优势。

  3. 示例代码

    import time
    from concurrent.futures import ProcessPoolExecutor
    def run(i):
    print(f'这是参数{i} 开始')
    time.sleep(1)
    print(f'这是参数{i} 结束')
    def main_process():
    pool = ProcessPoolExecutor(5)
    for i in range(1,10):
    pool.submit(run, i)
    if __name__ == '__main__':
    main_process()

总的来说,如果任务主要是 I/O 密集型的,那么线程池通常是更好的选择,而如果任务主要是 CPU 密集型的,那么进程池可能更适合。在实际应用中,可以根据任务的性质和系统资源进行选择。

(2)返回值

  • res = pool. Submit(run, i)
  • print(f'这是pool 的返回值 {res.result()}')
import time
from concurrent.futures import ProcessPoolExecutor
def run(i):
print(f'这是参数{i} 开始')
time.sleep(1)
print(f'这是参数{i} 结束')
return i**2
def main_process():
pool = ProcessPoolExecutor(5)
for i in range(1,10):
res = pool.submit(run, i)
print(f'这是pool 的返回值 {res.result()}')
if __name__ == '__main__':
main_process()

(3)shutdown()

  • 等待所有子进程结束,拿到结果
import time
from concurrent.futures import ProcessPoolExecutor
def run(i):
print(f'这是参数{i} 开始')
time.sleep(1)
print(f'这是参数{i} 结束')
return i**2
def main_process():
res_list = []
pool = ProcessPoolExecutor(5)
for i in range(1,10):
res = pool.submit(run, i)
res_list.append(res)
pool.shutdown()
for res in res_list:
print(f'这是pool 的返回值 {res.result()}')
if __name__ == '__main__':
main_process()

(4)异步回调函数

  • 异步回调函数是一种编程模式,常用于处理异步操作完成后的结果。在异步编程中,某些操作可能需要花费一定的时间来完成,但是我们不希望在等待这些操作完成时阻塞程序的执行,因此我们会将这些操作放在后台执行,并在其完成后通知主程序。

  • 异步回调函数通常用于以下情况:

  1. 异步 I/O 操作:例如网络请求、文件读写等,这些操作可能需要花费较长时间,我们不希望在等待它们完成时阻塞程序的执行。

  2. 事件处理:例如 GUI 应用程序中的事件响应,当用户触发某些事件时,我们可能需要执行一些操作,并在操作完成后通知用户或更新界面。

  • 异步回调函数的工作流程通常是这样的:
  1. 我们定义一个异步操作,例如一个函数,它可能会异步执行某些耗时的任务,并在任务完成后调用一个回调函数。

  2. 在调用异步操作时,我们通常会提供一个回调函数作为参数,以便在操作完成后被调用。

  3. 异步操作在后台执行,不会阻塞程序的执行。当操作完成后,会自动调用提供的回调函数,并将结果传递给它。

  • 异步回调函数有助于编写高效的异步程序,使得程序能够更好地利用资源,并提高响应速度。在 Python 中,异步编程可以使用 asyncioconcurrent.futures 等模块来实现。
from concurrent.futures import ThreadPoolExecutor
def task(n):
# 模拟一个耗时的任务
result = n * n
return result
def callback(future):
# 回调函数,在任务完成时被调用
print("任务完成,结果为:", future.result())
def main():
# 创建线程池
t = ThreadPoolExecutor(3)
# 提交任务并设置回调函数
future1 = t.submit(task, 5)
future1.add_done_callback(callback)
future2 = t.submit(task, 10)
future2.add_done_callback(callback)
future3 = t.submit(task, 15)
future3.add_done_callback(callback)
# 手动关闭线程池
t.shutdown()
if __name__ == "__main__":
main()

总结

from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
pool = ProcessPoolExecutor(5)
res = pool.submit(task,i).add_done_callback(callback)
posted @   ssrheart  阅读(58)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示