导语
QRunnable 是所有 runnable 对象的基类,而 QThreadPool 类用于管理 QThreads 集合。
QRunnable 类是一个接口,用于表示一个任务或要执行的代码,需要重新实现 run() 函数。
QThreadPool 管理和循环使用单独的 QThread 对象,以帮助程序减少创建线程的成本。每个 Qt 应用程序都有一个全局 QThreadPool 对象,可以通过调用 globalInstance() 访问。
作为Qt类中少有的基类, QRunnable提供了简洁有效的可运行对象的创建. 用QRunnable来创建独立的运行对象来运行 不涉及界面元素的数据处理过程 非常合适.
优点: 创建过程简洁, 使用方便, 配合着自身的autoDelete特性, 有点“招之即来, 挥之即去”的感觉.
缺点: 无法实时提供自身的运行状态.
QThreadPool
QThreadPool 支持多次执行相同的 QRunnable,通过调用 QThreadPool::tryStart(this) 从 run() 函数内。如果启用了 autoDelete,当最后一个线程退出 run() 函数,QRunnable 将被删除。多次调用 QThreadPool::start() 使用相同的 QRunnable,当启用 autoDelete 时会创建一个竞争条件,不推荐使用。
一定时间未使用线程将会到期,默认到期超时是 30000 毫秒(30秒)。可以使用 setExpiryTimeout() 来改变,设定一个负值,则会禁用到期机制。
调用 maxThreadCount() 查询使用线程的最大数量。如果需要,可以使用 setMaxThreadCount() 进行更改。默认的 maxThreadCount() 是 QThread::idealThreadCount()。activeThreadCount() 函数返回当前正在工作线程的数量。
reserveThread() 函数储备一个线程用于外部使用。当线程完成后,使用 releaseThread(),以便它可以被重新使用。从本质上讲,这些函数暂时增加或减少活跃线程的数量,并且当实现耗时的操作时对 QThreadPool 是不可见的,这比较有用。
注意: QThreadPool 是一个管理线程的低级类,高级替代品可以用 Qt Concurrent 模块。
基本使用
要使用 QThreadPool 的一个线程,子类化 QRunnable 并实现 run() 虚函数。然后创建一个对象,并把它传递给 QThreadPool::start()。
class HelloWorldTask : public QRunnable
{
void run() {
qDebug() << "Hello world from thread " << QThread::currentThread();
}
}
HelloWorldTask *hello = new HelloWorldTask();
// QThreadPool取得所有权,并自动删除 hello
QThreadPool::globalInstance()->start(hello);
默认情况下,QThreadPool 会自动删除 QRunnable。可以使用 QRunnable::setAutoDelete() 来改变自动删除标志。
和QThread的区别
QRunnable与QThread的区别
1.与外界通信方式不同。由于QThread是继承于QObject的,但QRunnable不是,所以在QThread线程中,可以直接将线程中执行的结果通过信号的方式发到主程序,而QRunnable线程不能用信号槽,只能通过别的方式,等下会介绍。
2.启动线程方式不同。QThread线程可以直接调用start()函数启动,而QRunnable线程需要借助QThreadPool进行启动。
3.资源管理不同。QThread线程对象需要手动去管理删除和释放,而QRunnable则会在QThreadPool调用完成后自动释放。