QThreadPool
一、描述
QThreadPool 类管理 QThread 的集合。
QThreadPool 管理和回收单独的 QThread 对象,以减少使用线程的程序中的线程创建成本。
每个 Qt 应用程序都有一个全局 QThreadPool 对象,可以通过调用 globalInstance() 来访问它。
要使用 QThreadPool,需要子类化 QRunnable 并实现 run() 虚函数。然后创建该类的对象并将其传递给 QThreadPool::start()。QThreadPool 默认自动删除 QRunnable。
QThreadPool 是管理线程的低级类,Qt Concurrent 模块是更高级的方案。
class HelloWorldTask : public QRunnable
{
void run() override
{
qDebug() << "Hello world from thread" << QThread::currentThread();
}
};
HelloWorldTask *hello = new HelloWorldTask();
// QThreadPool 取得 hello 的所有权并自动删除它
QThreadPool::globalInstance()->start(hello);
二、属性成员
1、activeThreadCount : const int
线程池中的活动线程数。
2、expiryTimeout : int
在 expiryTimeout 毫秒内未使用的线程被认为已过期并将退出。此类线程将根据需要重新启动。 默认是30000 毫秒(30 秒)。
如果此属性为负,则新创建的线程不会过期,例如,直到线程池被销毁它们才会退出。
设置 expiryTimeout 对已经运行的线程没有影响。
建议在创建线程池之后调用 start() 之前设置此属性。
3、maxThreadCount : int
线程池使用的最大线程数。默认值是 QThread::idealThreadCount()。
注意:线程池将始终使用至少 1 个线程,即使 maxThreadCount 设置为零或负数。
4、stackSize : uint
线程池工作线程的堆栈大小。默认值为 0,表示 QThread 使用操作系统默认堆栈大小。
更改它对已创建或正在运行的线程没有影响。
5、threadPriority : QThread::Priority
新工作线程的线程优先级。
该属性的值仅在线程池启动新线程时使用。 更改它对已经运行的线程没有影响。
默认值为 QThread::InheritPriority,这使得 QThread 使用与 QThreadPool 对象所在的优先级相同的优先级。
三、成员函数
1、~QThreadPool()
销毁 QThreadPool。此函数将阻塞,直到所有QRunnable完成。
2、void clear()
从队列中删除尚未启动的QRunnable对象。删除 QRunnable::autoDelete() 返回 true 的对象。
3、bool contains(const QThread *thread)
thread是否由线程池管理的线程。
4、[static] QThreadPool *globalInstance()
获取全局 QThreadPool 对象。
5、void start(QRunnable *runnable, int priority = 0)
保留一个线程并使用该线程来运行runnable,(除非该线程会使当前线程计数超过maxThreadCount())。runnable 会被添加到运行队列中。优先级参数可用于控制运行队列的执行顺序。
- 如果 runnable->autoDelete() 返回 true,线程池将拥有 runnable 的所有权,并且 runnable->run() 返回后,线程池将自动删除 runnable。
- 如果 runnable->autoDelete() 返回 false,则 runnable 的所有权仍归调用者所有。
在调用此函数后更改 runnable 的自动删除(QRunnable::setAutoDelete())会导致未定义的行为。
6、void start(std::function<void ()> functionToRun, int priority = 0)
重载函数。
例:
#include <QThreadPool>
#include <functional>
void showMSG()
{
qDebug()<<"showMSG Thread ID:"<<QThread::currentThreadId();
qDebug()<<"run showMSG";
}
int main(int argc, char *argv[])
{
qDebug()<<"main Thread ID:"<<QThread::currentThreadId();
std::function<void()> fun = showMSG;
QThreadPool::globalInstance()->start(fun);
}
7、bool tryStart(QRunnable *runnable)
尝试保留一个线程来运行 runnable。
如果调用时没有可用线程,则此函数不执行任何操作并返回 false。 否则 runnable 将立即使用一个可用线程运行,并且返回 true。
关于runnable对象的所有权见上面的start()。
8、bool tryStart(std::function<void ()> functionToRun)
重载函数。
尝试保留一个线程来运行 functionToRun。
如果调用时没有可用线程,则此函数不执行任何操作并返回 false。 否则 functionToRun 立即使用一个可用线程运行,并且返回 true。
9、bool tryTake(QRunnable *runnable)
如果runnable尚未启动,则尝试从队列中删除指定的 runnable。
如果 runnable 尚未启动,则返回 true,并且 runnable 的所有权转移给调用者(即使 runnable->autoDelete() == true)。 否则返回false。
注意:如果runnable->autoDelete() == true,这个函数可能会删除错误的runnable。 这被称为 ABA 问题:原始的 runnable 可能已经执行并已被删除。 内存被重新用于另一个QRunnable 对象。因此,我们建议仅对未自动删除的QRunnable 对象调用此函数。
10、bool waitForDone(int msecs = -1)
让所有线程退出并从线程池中删除所有线程,最多等待 msecs 毫秒然后看退出和删除的结果。如果删除了所有线程返回 true,否则返回false。 如果 msecs 为 -1(默认值),则忽略超时(等待最后一个线程退出)。
11、void reserveThread()
保留一个线程,不考虑 activeThreadCount() 和 maxThreadCount()。
调用此函数后应调用releaseThread() 以允许重用它。
注意:此函数将始终增加活动线程的数量。 这意味着通过使用这个函数,activeThreadCount() 有可能返回一个大于 maxThreadCount() 的值。
12、void releaseThread()
释放先前通过调用reserveThread() 保留的线程。(处理activeThreadCount() 有可能返回一个大于 maxThreadCount() 的值的情况,以便线程池可以正确控制activeThreadCount())
QRunnable
一、描述
QRunnable 类是一个接口,用于表示需要执行的任务或代码段,由重新实现的 run() 函数表示。
可以使用 QThreadPool 在单独的线程中执行代码。
二、成员函数
1、[static] QRunnable *create(std::function<void ()> functionToRun)
创建一个在 run() 中调用 functionToRun 的 QRunnable。默认情况下启用自动删除。
2、void run()
线程中要执行的代码。
3、void setAutoDelete(bool autoDelete)
设置是否启用自动删除。
如果开启了自动删除,QThreadPool会在调用run()后自动删除这个QRunnable 对象。
请注意,必须在调用 QThreadPool::start() 之前设置此标志。在 QThreadPool::start() 之后调用此函数会导致未定义的行为。
当启用 autoDelete 时,使用相同的 QRunnable 多次调用 QThreadPool::start() 会产生race condition(竞争条件:多个线程同时访问相同的共享数据,而造成数据的不一致性),因此不推荐使用。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)