第六章 QT基础:8、Qt中线程池的使用

1. 线程池的原理

在传统多线程编程中:

  • 每来一个任务就创建一个新线程
  • 任务结束后销毁线程
    这样做简单,但如果任务量巨大、每个任务又很短,就会导致:
  • 频繁创建、销毁线程 ➔ 极大浪费系统资源 ➔ 程序变慢
线程池的出现,就是为了解决这个问题!

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程可以排队,但他们要等到其他线程完成后才启动。


什么是线程池?

  • 线程池事先创建好一定数量的线程(工作线程)
  • 新任务来了,不创建新线程,而是把任务交给已有的线程来执行
  • 任务完成后,线程不销毁,而是回到池中,等待下一个任务
  • 大幅减少了线程创建销毁的开销,提高了程序性能

线程池组成:

线程池的要分为3个部分,这三部分配合工作就可以得到一个完整的线程池:

组成 说明
任务队列 存放所有等待执行的任务
工作线程 多个,循环取任务队列里的任务来执行
管理者线程 1个,动态监控线程数量,按需扩缩线程池
① 任务队列
  • 存储需要处理的任务,由工作线程来取出并执行。
  • 通过线程池提供的API函数(比如 start()),可以:
    • 把新任务添加到任务队列中(等待线程来处理)
    • 或者从任务队列中删除还没执行的任务(比如 clear()tryTake()
  • 已处理完的任务,会被自动从任务队列里移除。

✅ 理解:
任务队列就像"待办事项清单",新的任务不断加进来,做完就从清单上划掉。


② 生产者线程(调用线程池添加任务的线程)
  • 线程池的使用者(你的程序中的主线程、其他业务线程)就是生产者线程
  • 他们的任务是:
    • 通过调用线程池API(比如 start()
    • 把要处理的新任务丢进任务队列里
      ✅ 理解:
      生产者线程就是不停地往线程池扔任务的人,比如主程序发出10个图片处理任务。

③ 工作线程(处理任务队列的线程,N个)
  • 线程池内部会维护一定数量的工作线程(比如4个,8个,或更多)。
  • 工作线程不断从任务队列里取任务出来执行。
  • 工作线程扮演的是消费者角色(消费任务队列里的任务)。

✅ 工作线程的行为规则:

  • 如果任务队列为空,工作线程会被阻塞等待(用条件变量或信号量机制)。
  • 一旦有新任务加入,生产者线程会"通知"(唤醒)一个或多个工作线程去继续干活!
    ✅ 理解: 工作线程就像在仓库门口排着的工人,一有新货(新任务),马上有人上来干活。

④ 管理者线程(通常1个)
  • 管理者线程不直接处理任务,只负责管理和监控整个线程池状态。
  • 它的主要工作:
    • 周期性检测任务队列中待处理的任务数量
    • 统计当前有多少线程是处于繁忙状态
  • 动态调整线程池规模:
    • 当任务过多 ➔ 可以增加一些新的工作线程
    • 当任务很少 ➔ 可以减少空闲工作线程,节省资源
      ✅ 理解:
      管理者线程就像一个车间班长,负责调度:活太多叫更多工人加班,活少了就让人休息。
      ![[Pasted image 20250428140801.png]]

2. QRunnable 类(表示线程池中的单个任务)

✅ 在Qt中使用线程池需要先创建任务,添加到线程池中的每一个任务都需要是一个QRunnable类型,因此在程序中需要创建子类继承QRunnable这个类,然后重写 run() 方法,在这个函数中编写要在线程池中执行的任务,并将这个子类对象传递给线程池,这样任务就可以被线程池中的某个工作的线程处理掉了。


QRunnable类关键API

方法 作用
void run() override **必须重写!**任务执行的具体逻辑写这里
void setAutoDelete(bool) 设置任务执行完后,是否自动销毁
bool autoDelete() const 查询当前任务是否自动析构

自定义一个任务类示例

(如果需要使用Qt信号槽)
class MyWork : public QObject, public QRunnable
//继承QObject和QRunnable(多继承)
{
   
   
    //必须继承QObject,才能使用信号槽机制
    Q_OBJECT
public:
    explicit MyWork(QObject *parent = nullptr)
    {
   
   
        setAutoDelete(true); // 任务完成后自动销毁
    }
    ~MyWork();

    void run() override; // 重写run(),任务逻辑写这里
};

✅ 继承QObject + QRunnable,可以发送信号、响应槽,功能更强!


(如果不需要信号槽)
class MyWork : public QRunnable
{
   
   
public:
    explicit MyWork()
    {
   
   
        setAutoDelete(true);
    }
    ~MyWork();

    void run() override;
};

✅ 只继承QRunnable,轻量,专注执行任务。


3. QThreadPool 类(线程池管理器)

Qt官方提供的线程池管理类。


QThreadPool类常用API

<
方法 说明
int maxThreadCount() 获取最大线程数量
void setMaxThreadCount(int) 设置最大线程数量
void start(QRunnable *task, int priority = 0) 把任务扔进线程池
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值