PySide6/PyQT多线程之 线程池的基础概念和最佳实践

news/2024/7/7 20:25:04

在这里插入图片描述

前言

PySide6/PyQT 多线程编程中,线程池也是重要的一项知识点,线程池是一种高效管理和调度多个线程执行任务的方式。
通过结合线程池(QThreadPool)和任务类(QRunnable),可以轻松地实现并发执行任务、提高应用程序的性能,并更好地控制代码逻辑和资源的管理。

值得注意的是,在使用 QRunnableQThreadPool 的线程池中,每个任务(QRunnable 对象)会被分配到不同的线程执行,每个线程拥有自己的任务和局部数据。因此,默认情况下,每个任务在自己的线程中是相互独立的,不会直接共享资源。

知识点📖📖

本文用到的几个PySide6/PyQT的知识点及链接。

作用链接
对象间通信的机制,允许对象发送和接收信号Signal
用于响应Signal信号的方法Slot
可运行的任务类,用于封装要在后台线程中执行的代码逻辑QRunnable
线程池类,用于管理和调度多个线程执行 QRunnable 任务QThreadPool

基础概念

QRunnable

一个接口类,用于表示可以在线程中执行的任务。通过继承 QRunnable 并实现 run 方法,可以定义任务的逻辑。

QThreadPool

一个管理线程的线程池类。它可以管理和执行 QRunnable 对象,并自动管理线程的创建、回收和重用。

QThreadPool 可以限制并发线程的数量,防止资源过度占用。

QRunnable 更适合用于执行短期、轻量级的任务,而 QThread 更适合用于需要更多控制和状态管理的长期任务。

使用 QRunnableQThreadPool 的优势在于线程的创建和管理交由线程池处理,可以避免频繁创建和销毁线程,提高效率,并根据系统资源和任务数量自动调整线程的数量。



创建线程池步骤

创建自定义任务类(QRunnable

  • 创建继承自 QRunnable 的自定义任务类。在任务类中实现 run() 方法,该方法包含要在后台线程中执行的代码逻辑。
class Worker(QRunnable):
    def __init__(self, func, *args, **kwargs):
        super().__init__()
        self.func = func
        self.args = args
        self.kwargs = kwargs

    def run(self):
        # 执行任务函数,并传递参数
        self.func(*self.args, **self.kwargs)

创建线程池对象(QThreadPool

  • 在应用程序中创建一个线程池对象。通过直接实例化 QThreadPool 或使用 QThreadPool.globalInstance() 方法获取全局线程池实例。
def main():
    # 创建线程池对象
    threadpool = QThreadPool()

创建任务对象并提交给线程池

  • 创建一个任务对象,将其实例化为自定义任务类的实例。
  • (可选)可以通过构造函数传递任务所需的函数、参数或其他数据。
  • 使用线程池的 start() 方法将任务对象提交给线程池执行。
# 示例任务函数
def task_func():
    # 耗时操作
   
# 创建任务对象并提交给线程池
task1 = Worker(task_func, "John")
threadpool.start(task1)

task2 = Worker(task_func, "Alice")
threadpool.start(task2)

与QThread相比较

优势有挺多的,参考如下:

  • 将任务的执行和线程管理分离,使代码更具可维护性和可扩展;
  • 管理和控制多个任务的并发执行,以最大程度地利用系统资源;
  • 在需要执行大量独立任务或耗时操作的情况下,提供一种高效的并发处理方式;
  • 提高应用程序的响应性,通过并行执行任务,减少主线程的负载,避免阻塞用户界面;
  • 通过将任务逻辑封装在 QRunnable 中,并使用 QThreadPool 进行任务的调度和管理,轻松实现多线程应用程序,提高性能和响应性,并且更好地控制和组织代码。
  • 自动管理线程的创建、回收和重用,避免频繁创建和销毁线程,从而减少了线程切换和资源消耗。线程池可以重用线程,避免了重复创建线程的开销。

总结

综上所述,使用 QRunnable 和 QThreadPool 相对于直接使用 QThread 提供了更高级的线程管理功能、更好的性能优化、更好的并发控制和更好的可扩展性。

它通过自动管理线程的创建和回收、动态调整线程数量、限制并发线程的数量等机制,减少了线程切换和资源消耗,提高了整体系统性能和稳定性。

同时,将任务逻辑封装在 QRunnable 中,使代码更清晰和可维护,并提供了更灵活的任务管理方式。

常用方法

threadpool = QThreadPool()

常用的方法列举在这里,

代码释义
start(QRunnable)将一个任务(QRunnable 对象)提交给线程池执行
activeThreadCount()返回当前正在执行任务的线程数
maxThreadCount()返回线程池允许的最大线程数
waitForDone(msecs = -1)等待线程池中的所有任务执行完成,或者等待指定的毫秒数。如果设置为 -1,则会一直等待直到所有任务完成
clear()清除线程池中所有待执行的任务,但不会停止正在执行的任务

代码展示

这只是一份简单的线程池模板,没啥用~

import time
from PySide6.QtCore import (QRunnable, QThreadPool, Qt)



# 自定义的工作任务类
class Worker(QRunnable):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        print(f"Worker {self.name} started")
        time.sleep(2)  # 模拟一些耗时的工作
        print(f"Worker {self.name} finished")


def main():
    # 创建线程池
    thread_pool = QThreadPool()

    # 设置最大线程数
    thread_pool.setMaxThreadCount(4)

    # 创建工作任务并将其添加到线程池
    for i in range(1, 6):
        worker = Worker(f"Task {i}")
        thread_pool.start(worker)

    # 在等待所有任务完成之前,阻塞主线程
    thread_pool.waitForDone()
    print("All tasks completed")


if __name__ == "__main__":
    main()

代码释义

  1. 定义工作任务类:定义了一个名为Worker的自定义类,它继承自QRunnable类。这个类表示一个工作任务,具体的工作逻辑定义在run方法中。

  2. Worker类的__init__方法:这个方法用于初始化工作任务对象。在这个示例中,将每个工作任务命名为name,并将其保存在self.name属性中。

  3. Worker类的run方法:这个方法表示工作任务的执行逻辑。在示例中,打印工作任务的名称,然后使用time.sleep方法模拟一些耗时的工作(2秒),最后再次打印工作任务的名称。

  4. main函数:程序的入口点。在这个函数中执行以下操作:

    • 创建线程池:使用QThreadPool()创建一个全局的线程池对象thread_pool
    • 设置最大线程数:使用setMaxThreadCount方法设置线程池的最大线程数为4。
    • 创建工作任务并添加到线程池:使用一个循环创建了5个工作任务,每个任务都有一个唯一的名称。然后,使用start方法将这些工作任务添加到线程池中,以便并行执行。
    • 阻塞主线程直到任务完成:使用waitForDone方法阻塞主线程,直到所有任务完成执行。
    • 打印所有任务完成的消息:在所有任务完成后,打印"All tasks completed"的消息。

这份代码创建了一个线程池并将多个工作任务添加到线程池中执行。
每个任务都是通过继承QRunnable类并实现run方法来定义的。通过使用线程池,这些工作任务可以在多个线程中并行执行,从而提高程序的效率。
最后,等待所有任务完成后,打印出任务完成的消息。

总结🎈🎈

本文介绍了PySide6/PyQT线程池的基本概念和使用方法。介绍了QRunnableQThreadPool的作用,以及它们结合在一起的优势。

通过使用QRunnableQThreadPool,可以将任务的执行和线程管理分离,提高应用程序的性能和响应性。

我建议常见的多线程场景都用上线程池,省事~

后话

本次分享到此结束,
see you~~🐱‍🏍🐱‍🏍


http://lihuaxi.xjx100.cn/news/1151354.html

相关文章

【已解决】grub引导项修复:Minimal BASH-like line editing is supported.

目录 1 问题背景2 问题探索3 问题解决4 告别Bug 1 问题背景 环境: Win10Ubuntu20.04 现象:双系统电脑向移动硬盘安装Ubuntu系统后,重启黑屏并显示Minimal BASH-like line editing is supported. For the first word, TAB lists possible comm…

一、通过命令行体验长安链

一、通过命令行体验长安链 1 、概述2、环境依赖2.1、硬件依赖2.2、软件依赖2.3、git安装2.4、golang安装2.5、gcc 3、环境搭建3.1、源码下载3.2、 源码编译3.3、编译及安装包制作3.4、启动节点集群3.5、查看节点启动使用正常 4、使用CMC命令行工具部署、调用合约4.1、编译&…

【MYSQL】事务的4大属性,对隔离级别的详细讲解

目录 1.原子性和持久性 1.1.手动提交事务 1.2.自动提交事务 1.3.事务的原理: 2.隔离性 1.读未提交(Read Uncommitted) 2.读提交(Read Committed) 3.可重复读 4.串行化 3.一致性 4.理解读提交和可重复读的实现…

hadoop各种配置文件的含义及作用

文件描述core-default.xml该文件包含了对于 Hadoop 核心部分的默认配置,例如 I/O 设置、网络设置、副本设置等hdfs-default.xml该文件包含了对于 Hadoop 分布式文件系统(HDFS)的默认配置,例如 NameNode 和 DataNode 的地址、端口、…

〖Python网络爬虫实战㉖〗- Selenium库和ChromeDriver驱动的安装

订阅:新手可以订阅我的其他专栏。免费阶段订阅量1000 python项目实战 Python编程基础教程系列(零基础小白搬砖逆袭) 说明:本专栏持续更新中,目前专栏免费订阅,在转为付费专栏前订阅本专栏的,可以免费订阅付…

chatgpt赋能Python-python3捕获异常

Python3异常处理技术详解 在Python3中,异常处理技术是一项非常重要的工具。它能够帮助程序员避免不可预见的错误,减少不必要的程序崩溃,保证程序的稳定性。 什么是异常? 异常就是程序在执行过程中发生的错误或异常情况。不同的…

【Markdown】笔记

设置-通用-开启调试模式 普通文本编辑器编写的轻量级标记语言 标题 # ~ ###### 文本 _斜体_ *斜体* **粗体** ***粗斜体*** 列表 无序 * - 有序 1. 2. 3. Tab控制层级 链接 [链接名](链接地址) <链接地址> 引用 > 嵌套 > >> >>&…

图片隐写(一)

文件隐藏 binwalk binwalk -e filename foremost foremost filename steghide & stegseek Install sudo apt-get install steghidestegseek Use steghide extract -sf filename -p passwordtime stegseek secret.file aaa.txt dd 文本隐藏 二进制文件末尾 or 文…