Python线程池thread pool创建使用及实例代码分享

Python线程池thread pool创建使用及实例代码分享

Python线程池(thread pool)是一种提供线程复用的机制,通过线程池的管理,可以减少线程创建与销毁的代价,并提升异步并发执行的性能,同时避免资源的浪费,使用起来也相对方便和稳定。本篇攻略将详细介绍如何在Python中使用线程池,通过实例代码的分享帮助读者更好的掌握线程池的使用和工作原理。

创建线程池

Python内置了线程池的支持,使用concurrent.futures模块中的ThreadPoolExecutor类可以方便地创建线程池。

首先,需要导入concurrent.futures模块,以及time模块用于辅助时间计算。

import concurrent.futures
import time

然后,可以通过如下方式创建一个具有4个线程的线程池。

with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
    # TODO: 任务列表

可以看到,在创建线程池时,可以通过max_workers参数指定线程池中线程的数量,具体数量应该根据具体的场景来确定。同时,在使用完线程池后,需要使用with语句来自动管理线程池的资源。

提交任务

线程池中的工作线程需要执行的任务通过提交操作放入线程池中,线程池会自动选择适当的线程来执行任务。一般情况下,任务都是使用函数的形式传递给线程池。

举个例子,假设有一个需要执行的计算任务,可以通过如下方式定义计算函数。

def compute(num):
    result = num * num
    time.sleep(1)  # 模拟耗时操作
    return result

该函数接收一个参数num,返回num的平方,并使用time.sleep函数模拟耗时操作。

接下来,可以通过使用submit方法将任务提交到线程池中。

with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
    future_list = []
    for i in range(10):
        future = executor.submit(compute, i)
        future_list.append(future)

可以看到,在遍历任务列表时,可以使用submit方法将任务提交到线程池中,并使用future_list保存任务的结果。submit方法的第一个参数是需要执行的函数,后续的参数是函数的输入参数。

获取结果

线程池中的任务是异步执行的,因此主线程需要使用future对象来获取线程执行的结果。future对象对应一个线程任务,其中包含了线程执行结果和执行状态等参数。

可以使用done方法判断任务是否已经完成,使用result方法获取任务的返回值,如下所示。

with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
    future_list = []
    for i in range(10):
        future = executor.submit(compute, i)
        future_list.append(future)

    for future in concurrent.futures.as_completed(future_list):
        if future.done():
            print("result: {}".format(future.result()))

可以看到,在使用as_completed方法迭代线程任务时,可以使用future.done()方法判断线程是否执行完,使用future.result()方法获取线程执行结果。

示例说明1:异步下载图片

假设要异步下载多张图片并保存到本地,可以通过使用线程池实现,具体步骤如下。

首先,需要导入requests模块和os模块,后者用于保存图片。

import requests
import os

然后,可以定义下载函数,将图片和本地文件名作为输入参数。

def download_img(url, filename):
    response = requests.get(url, stream=True)
    with open(filename, 'wb') as f:
        for chunk in response.iter_content(1024):
            f.write(chunk)

注意,download_img函数将使用requests.get方法下载图片内容,并使用stream=True参数设置为分块读取,以便在下载大文件时不会占用太多内存。下载完成后,将图片内容保存到指定的文件中。

接下来,可以通过使用线程池,并构造许多下载任务来完成异步下载图片的工作。

with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
    urls = ["https://picsum.photos/200/300?random={}".format(i) for i in range(10)]
    filenames = [os.path.join(os.getcwd(), "img{}.jpg".format(i)) for i in range(10)]

    future_list = []
    for i in range(10):
        future = executor.submit(download_img, urls[i], filenames[i])
        future_list.append(future)

    for future in concurrent.futures.as_completed(future_list):
        if future.done():
            print("download {} complete".format(future.args[1]))

在上面的代码中,首先构造了10个图片的URL和下对应的文件名,并使用线程池构造了10个下载任务,并将任务的future对象保存在列表中。随后,可以使用as_completed方法依次判断并输出每个任务的状态。

示例说明2:并发执行多个命令

假设要在本地同时执行多个操作系统命令,并等待所有命令执行完成后再输出相应结果,可以通过使用线程池实现。

首先,需要将命令列表构造出来。

commands = ['echo Hello', 'echo World', 'ls -l']

然后,定义命令执行函数。

def run_command(command):
    print("Running command: {}".format(command))
    result = os.popen(command).read()
    time.sleep(1)  # 模拟耗时操作
    return result

在该函数中,首先输出将要执行的命令,然后使用os.popen执行相应命令,并将执行结果保存到返回值中。

然后,可以通过使用线程池,并构造许多命令执行任务来完成异步执行命令的工作。

with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
    future_list = []
    for command in commands:
        future = executor.submit(run_command, command)
        future_list.append(future)

    for future in concurrent.futures.as_completed(future_list):
        if future.done():
            print("result: {}".format(future.result()))

在上述代码中,首先构造了命令列表,并使用线程池构造了多个命令任务,并将任务的future对象保存在列表中。随后,可以使用as_completed方法依次判断并输出每个任务的执行结果。

总结

Python线程池提供了高效的管理方式和执行异步任务的能力,同时使用也非常简单明了,可以极大提升代码的执行效率和并行性。通过上述示例,相信读者已经对Python线程池有了一定的了解,可以在实际项目中灵活应用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python线程池thread pool创建使用及实例代码分享 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • Python Ruby 等语言弃用自增运算符原因剖析

    Python、Ruby等语言弃用自增运算符原因剖析 在Python、Ruby等动态语言中,不再支持自增运算符(++)的使用,其原因主要有以下几点: 1. 语法歧义 在C语言中,自增运算符可以放在变量名前或者后面,但是在不同的语法环境下会产生不同的意义。 例如: int a = 1, b = 0; b = a++; // 等价于 b = a; a = a + …

    python 2023年5月13日
    00
  • 计算一个二维NumPy数组中所有列的总和

    计算一个二维NumPy数组中所有列的总和的完整攻略如下: 导入NumPy模块:在使用NumPy计算数组的列总和之前,需要先导入NumPy模块。可以使用以下语句导入NumPy模块: import numpy as np 创建二维NumPy数组:接下来需要创建一个二维NumPy数组。可以使用以下语句创建一个二维数组: arr = np.array([[1, 2,…

    python-answer 2023年3月25日
    00
  • python实现飞机大战游戏(pygame版)

    Python实现飞机大战游戏(pygame版)攻略 1. 简介 飞机大战游戏是一款非常经典的游戏,它在多个平台上都有发行。在Python中,我们可以使用pygame模块来实现这个游戏。 2. 安装pygame模块 首先,你需要安装pygame模块。可以使用以下命令在终端中安装: pip install pygame 3. 实现游戏窗口 使用pygame模块创…

    python 2023年6月2日
    00
  • 通过python获取注册域名

    【问题标题】:Get registered domains by python通过python获取注册域名 【发布时间】:2023-04-02 14:35:02 【问题描述】: 我想在 whois 域上做一个 python 程序。 我想获取每天在whois域中注册的信息。 寻找有一个whois library。 但是好像不能搜索每天获得的域名。 有没有办法在…

    Python开发 2023年4月8日
    00
  • python 实现二叉搜索树的四种方法

    Python 实现二叉搜索树的四种方法 二叉搜索树(Binary Search Tree,简称BST)是一棵二叉树,它具有以下性质: 若左子树不为空,则左子树上所有结点的值均小于它的根节点的值; 若右子树不为空,则右子树上所有结点的值均大于它的根节点的值; 左、右子树分别也为二叉搜索树; 没有键值相等的节点; 因其高效性,在排序、查找等问题中,常常使用二叉搜…

    python 2023年5月13日
    00
  • Python实现矩阵相乘的三种方法小结

    下面是关于“Python实现矩阵相乘的三种方法小结”的完整攻略。 问题描述 在数学中,矩阵相乘是一个常见的操作。在计算机科学中,矩阵相乘也是常见的一种运算。本文将介绍 Python 实现矩阵相乘的三种方法。 解决方案 方法一:使用循环实现矩阵相乘 思路:分别遍历两个矩阵的每个元素,计算它们的乘积,再求和,最终得到结果矩阵。 代码实现: def matrix_…

    python 2023年6月3日
    00
  • 【0基础学爬虫】爬虫基础之自动化工具 Pyppeteer 的使用

    大数据时代,各行各业对数据采集的需求日益增多,网络爬虫的运用也更为广泛,越来越多的人开始学习网络爬虫这项技术,K哥爬虫此前已经推出不少爬虫进阶、逆向相关文章,为实现从易到难全方位覆盖,特设【0基础学爬虫】专栏,帮助小白快速入门爬虫,本期为自动化工具 Pyppeteer 的使用。 概述 前两期文章中已经介绍到了 Selenium 与 Playwright 的使…

    python 2023年5月9日
    00
  • C# wpf Canvas中实现控件拖动调整大小的示例

    下面是详细讲解C# wpf Canvas中实现控件拖动调整大小的攻略。 1. 为控件添加事件处理程序 首先,我们需要定义控件的事件处理程序来让它们可以被拖动和调整大小。在XAML中,我们可以这样为控件添加鼠标左键按下事件处理程序: <Canvas> <Button Content="可拖拽" Canvas.Left=&q…

    python 2023年6月13日
    00
合作推广
合作推广
分享本页
返回顶部