QtApplets-线程池
今天咱们稍微看下Qt的线程池。QThreadPool
,浅浅搞一下。
QThreadPool
QThreadPool
是 Qt 框架中的一个类,用于管理和调度多线程任务的线程池。它提供了一种方便的方式来执行和管理 QRunnable
或 QThread
对象,并控制并发执行的线程数量。
以下是关于 QThreadPool 的一些主要功能:
- 全局线程池实例:Qt 提供了一个全局共享的线程池实例,可以通过 QThreadPool::globalInstance() 获取。
- 添加任务:可以使用 QThreadPool 的 start() 函数来添加任务。任务可以是继承自 QRunnable 的对象或继承自 QThread 的对象。
- 控制线程数量:可以使用 setMaxThreadCount() 函数设置线程池的最大线程数量。线程池将根据需要动态创建或销毁线程,以使线程数量保持在指定范围内。
- 队列管理:线程池使用一个任务队列来管理待执行的任务。当线程池中的线程完成任务时,它们将从队列中获取下一个任务并执行。
- 任务取消:可以使用 cancel() 函数来取消正在执行的任务。被取消的任务将不会被执行完毕。
QThreadPool 适用于并发执行大量相对简单的任务,例如计算密集型任务、网络请求等。如果您需要更高级的线程管理和结果处理,可以考虑使用 Qt 的其他多线程类和机制,如 QThread、QtConcurrent 等。总的来说,QThreadPool 是 Qt 框架中用于管理和调度多线程任务的线程池类。通过添加任务对象到线程池并控制线程数量,可以实现任务的并发执行和系统资源的高效利用。这样可以更好地利用系统资源,并实现任务的并行处理和异步操作。
QThreadPool 与 QThread 区别
QThread
和 QThreadPool
都是 Qt 框架中用于多线程编程的类,但它们的使用场景和方式有所不同。
QThread:
QThread
是一个线程类,可以创建和管理一个线程。- 你需要自己管理
QThread
的生命周期,包括创建、启动和销毁线程。 - 你可以通过继承
QThread
并重写其 run() 方法来定义线程的任务。 QThread
更适合长期运行的任务或者需要详细控制的任务。
QThreadPool:
QThreadPool
是一个线程池类,可以管理和复用多个线程。QThreadPool
会自动管理线程的生命周期,包括创建、启动和销毁线程。- 你可以通过创建 QRunnable 对象并将其添加到
QThreadPool
来定义线程的任务。 QThreadPool
更适合执行大量短期的任务,因为它可以复用线程,避免了频繁创建和销毁线程的开销。
总的来说,QThread 和 QThreadPool 的主要区别在于它们的管理方式和使用场景。你可以根据你的具体需求来选择使用哪一个。
替代方案
在 Qt 中,除了 QThread 和 QThreadPool,还有其他一些多线程编程的替代方案:
- Qt Concurrent:Qt Concurrent 提供了一种将任务分发到处理器所有的核的易用接口。线程代码完全被隐藏在 Qt Concurrent 框架下,所以你不必考虑细节。尽管如此,Qt Concurrent 不能用于线程运行时需要通信的情况,而且它也不应该被用来处理阻塞操作。
- WorkerScript:WorkerScript 是 QML 中的线程化。如果你正在使用 QML 进行开发,那么 WorkerScript 可能是一个很好的选择。
- 其他库:除了 Qt,还有一些其他的 C++ 库也提供了多线程支持,例如 Boost.Asio、Poco、ACE 等5。这些库的功能和 Qt 类似,但可能在某些特定的使用场景下更加适合。
Qt Concurrent
[参考链接](Qt并发模块Qt Concurrent的使用_qtconcurrent 用法-CSDN博客)
QtConcurrent
命名空间提供了高级 api,使得无需使用诸如互斥、读写锁、等待条件或信号量等低级线程原语就可以编写多线程程序。使用 QtConcurrent 编写的程序会根据可用的线程处理器核心数量自动调整使用的线程数,这意味着编写的应用程序在部署到多核系统时将自动扩展。
当你发现你自己的程序UI运行不流畅时可以尝试将执行计算的函数放到QtConcurrent::run()
中处理,这比改用QThread
方便得多。
QThreadPool 与 Qt Concurrent 区别
QThreadPool
和 Qt Concurrent
都是 Qt 框架中用于多线程编程的工具,但它们的使用方式和适用场景有所不同。
QThreadPool:
- QThreadPool 是一个线程池类,它可以管理和复用多个线程。
- 你可以通过创建 QRunnable 对象并将其添加到 QThreadPool 来定义线程的任务。
- QThreadPool 更适合执行大量短期的任务,因为它可以复用线程,避免了频繁创建和销毁线程的开销。
Qt Concurrent:
- Qt Concurrent 是一个命名空间,它提供了一些高级 API,使得无需使用诸如互斥、读写锁、等待条件或信号量等低级线程原语就可以编写多线程程序。
- 使用 Qt Concurrent 编写的程序会根据可用的线程处理器核心数量自动调整使用的线程数,这意味着编写的应用程序在部署到多核系统时将自动扩展。
- Qt Concurrent 提供了一些静态函数,可以运行自定义函数,也提供了对容器的操作函数。
Demo
首先,我们定义一个任务类,它继承自QRunnable
:
class Task : public QRunnable
{
protected:
void run() override
{
// 这里放置任务代码
qDebug() << "Task executed in thread" << QThread::currentThread();
// 模拟一些工作
QThread::sleep(1);
}
};
然后,在某个类中,我们使用QThreadPool来管理和执行这些任务:
// 获取全局线程池的实例
QThreadPool *pool = QThreadPool::globalInstance();
// 设置线程池中最大线程数
pool->setMaxThreadCount(5);
// 创建并启动任务
for (int i = 0; i < 10; ++i) {
Task *task = new Task();
// 如果不设置,则任务执行完毕后会自动删除
task->setAutoDelete(true);
pool->start(task);
}
// 等待所有任务完成,你可以设置一个超时或者无限等待
pool->waitForDone();
运行效果
这个源码都没有用到界面,如果要用到界面,那么在线程里面就需要发送信号了,因为大佬们都在推荐说线程里面不要操作UI的内容