线程池
reserveThread
其会占用线程池的活动线程数。这个应用场景是开辟单独的线程来处理,相当于用于管理单独的线程+线程池。
reserveThread会将QThreadPoolPrivate中的成员reservedThreads加1
QThreadPoolPrivate在计算活动线程数时,会将reservedThreads计算上
int QThreadPoolPrivate::activeThreadCount() const
{
return (allThreads.count()
- expiredThreads.count()
- waitingThreads.count()
+ reservedThreads);
}
启动任务
void start(QRunnable *runnable, int priority = 0)
线程池start启动时序为
- 调用QThreadPoolPrivate的tryStart尝试启动任务
- 失败时(活动线程数 ≥ \ge ≥最大线程数),会将任务放入任务队列中
- 如果存在等待线程,则从等待线程队列中取出第一个线程唤醒该线程
QThreadPoolPrivate尝试启动任务时序为
- 如果没有启动的线程,则创建线程启动
- 如果活动线程数 ≥ \ge ≥最大线程数,返回false
- 有等待线程,则将任务放入任务队列中,唤醒其中的一个等待线程
- 有超时线程,则重新启动超时线程
- 创建线程启动任务
QThreadPoolPrivate
其管理线程池的
QSet<QThreadPoolThread *> allThreads:线程池管理的所有线程
QQueue<QThreadPoolThread *> waitingThreads:等待线程
QQueue<QThreadPoolThread > expiredThreads:超时线程
QVector<QueuePage> queue:任务队列
QWaitCondition noActiveThreads:没有活动线程的条件变量
mutable QMutex mutex:数据同步互斥量
QThreadPoolThread
QWaitCondition runnableReady:运行准备好的条件变量
QThreadPoolPrivate *manager:线程所属的线程池
QRunnable *runnable:线程设置的任务
线程池线程运行调度
在runnableReady.wait唤醒时,如果在等待线程队列中可以删除该线程,则认为是超时了,后面会将线程放入超时线程队列中,并且退出线程循环
bool expired = manager->tooManyThreadsActive();
if (!expired) {
manager->waitingThreads.enqueue(this);
registerThreadInactive();
// wait for work, exiting after the expiry timeout is reached
runnableReady.wait(locker.mutex(), manager->expiryTimeout);
++manager->activeThreads;
if (manager->waitingThreads.removeOne(this))
expired = true;
if (!manager->allThreads.contains(this)) {
registerThreadInactive();
break;
}
}
if (expired) {
manager->expiredThreads.enqueue(this);
registerThreadInactive();
break;
}
因为在唤醒线程时,是从等待线程队列中取出后takeFirst再通过runnableReady条件变量wakeOne唤醒
d->waitingThreads.takeFirst()->runnableReady.wakeOne();