qt多线程之QThreadPool

线程池

1
n
QThreadPool
QRunnable
QThreadPoolPrivate
+QList<QPair>QRunnable,int<> queue
QThreadPoolThread

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启动时序为

QThreadPool QThreadPoolPrivate QWaitCondition start tryStart return false enqueueTask wakeOne opt [waitingThreads not empty] QThreadPool QThreadPoolPrivate QWaitCondition
  1. 调用QThreadPoolPrivate的tryStart尝试启动任务
  2. 失败时(活动线程数 ≥ \ge 最大线程数),会将任务放入任务队列中
  3. 如果存在等待线程,则从等待线程队列中取出第一个线程唤醒该线程

QThreadPoolPrivate尝试启动任务时序为

QThreadPoolPrivate QThreadPoolThread QWaitCondition tryStart new start return true return false enqueueTask wakeOne return true start return true new start return true alt [allThreads empty] [activeThreadCount >= maxThreadCount] [waitingThreads > 0] [expiredThreads not empty] QThreadPoolPrivate QThreadPoolThread QWaitCondition
  1. 如果没有启动的线程,则创建线程启动
  2. 如果活动线程数 ≥ \ge 最大线程数,返回false
  3. 有等待线程,则将任务放入任务队列中,唤醒其中的一个等待线程
  4. 有超时线程,则重新启动超时线程
  5. 创建线程启动任务

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:线程设置的任务
线程池线程运行调度

QThreadPoolThread QMutexLocker QRunnable QQueue QWaitCondition run lock unlock run relock loop [tooManyThreadsActive or queue empty] enqueue(this) wait opt [no tooManyThreadsActive] loop [tooManyThreadsActive] QThreadPoolThread QMutexLocker QRunnable QQueue QWaitCondition

在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();
Qt提供了一些类来支持多线程编程,其中最常用的是QThreadQThreadPoolQThread类是Qt中最基本的多线程实现类,它提供了一个线程对象,可以通过继承QThread类并实现run()方法来创建自己的线程。 下面是一个简单的例子: ```cpp class MyThread : public QThread { public: void run() override { // 在这里编写线程运行的代码 } }; // 创建线程对象并启动 MyThread thread; thread.start(); ``` 在这个例子中,我们继承了QThread类,并重写了它的run()方法,run()方法中编写的代码将在新线程中运行。然后,我们创建了一个MyThread对象,并通过调用start()方法来启动线程。 除了QThread外,Qt还提供了QThreadPool类来管理多个线程。QThreadPool类可以创建多个线程,并将任务分配给这些线程来执行。QThreadPool使用线程池技术来提高多线程应用程序的性能。 下面是一个简单的例子: ```cpp QThreadPool *pool = QThreadPool::globalInstance(); // 获取全局线程池对象 // 创建任务 QRunnable *myTask = new MyTask(); // 将任务添加到线程池中 pool->start(myTask); ``` 在这个例子中,我们获取了全局线程池对象,并创建了一个MyTask对象作为任务。然后,我们将任务添加到线程池中,并由线程池来决定将任务分配给哪个线程来执行。 需要注意的是,多线程编程涉及到许多复杂的问题,如线程安全、锁、信号与槽等,需要仔细设计和考虑。在使用多线程时,应该遵循一些基本的原则,如避免共享资源、避免阻塞操作等,以确保程序的正确性和性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kgduu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值