Qt-ThreadPool

本文深入探讨Qt线程池(QThreadPool)与事件循环(QEventLoop)的结合使用,展示如何通过QtConcurrent创建并管理多个线程,实现线程间的任务分配与通信。文章提供了详细的代码示例,包括线程池初始化、事件循环配置及信号槽机制的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

闲谈

前几篇,说了Qt线程的最常见的QThread和偷懒的QtConcurrent,这两者使用的场景是不同的,前者更具有交互型,后者独立。对于QtConcurrent这种高级API如何让他发挥极致呢,我们就要用到QThreadPool和完美的QEventLoop,当然C++11就是最强搭档。在实践中,再次体会到Qt的事件驱动框架,以及信号和槽。可以这样说:谈及Qt的线程,线程工作与卡槽中。本篇是看自Jason大神的开源项目,特别感谢,送个小星星,实在优秀,还在学习中。对于其使用场景等目前水平不涉及,再次略记一笔。

备战

  • 首先,对于std::function,这样一个一统天下的大将军打开了函数之间交流的道路,想去那就去那,参数。
  • QEventLoop,这样的护国法师使得帝国青山常在,生命。
  • QtConcurrent,可谓开国领袖,为我们撑起一片天,创建线程。
  • QThreadPool,好比矿产资源,线程管理者。

实战

    #define MAX_COUNT 10

    // 线程池
    threadPool = QSharedPointer<QThreadPool>(new QThreadPool);
    threadPool->setMaxThreadCount(MAX_COUNT);

    // 事件循环
    eventloops = QSharedPointer<QVector<QPointer<QEventLoop>>>(new QVector<QPointer<QEventLoop>>);
    eventloops->resize(MAX_COUNT);

    // 工作者
    workers = QSharedPointer<QVector<QPointer<WorkerHelp>>>(new QVector<QPointer<WorkerHelp>>);
    workers->reserve(MAX_COUNT);

    // 线程
    for(auto one = 0; one < MAX_COUNT; one++){
        
        auto funObj = [this](int index){
            qDebug() << "thread poor"<< index <<"id:" << QThread::currentThreadId();
            // 线程死循环
            QEventLoop loop;
            WorkerHelp woker;

            eventloops->append(&loop);
            workers->append(&woker);

            loop.exec();
        };

        // high-api
        QtConcurrent::run(threadPool.data(), funObj, one);
    }

如上,我们创建一个拥有10个线程的线程池,并开启每个线程,且每个线程都有一个事件循环和工作者。使用时,分配任意一个工作者任务即可。工作者如下:

class WorkerHelp : public QObject
{
    Q_OBJECT
public:
    explicit WorkerHelp(QObject *parent = nullptr);
    // 获取要执行的任务
    void startTask(const std::function<void()> &_task);

// or slots
public Q_SLOTS:
    // 卡槽中执行
    void working();

private:
   std::function<void()> task = nullptr;
};
WorkerHelp::WorkerHelp(QObject *parent)
    :QObject(parent){}

void WorkerHelp::startTask(const std::function<void ()> &_task)
{
    task = _task;
    // sig-slot
    QMetaObject::invokeMethod(
                this,
                "working",
                Qt::QueuedConnection
            );
}

void WorkerHelp::working()
{
    task();
}

使用如下

    // 使用 lambda ,std::function 函数高度自由
    workers->at(index)->startTask([a,b,c,....](){
       // task content
    });

线程终止,因为我们对每个线程开启事件循环,所以通过sig-slot通知loop-quit即可,如下

    // 线程quit 通过信号和槽
    for(auto &one : *eventloops){
        QMetaObject::invokeMethod( one.data(), "quit" );
    }
    threadPool->waitForDone();

本篇仍需更改,待续。

好的,我将分别为您解释 `threadpool`、进程状态以及 Qt 框架下如何管理线程池。 ### ThreadPool 线程池 **ThreadPool** 是一种用于管理和分配工作线程的机制。它允许应用程序通过预先创建一组固定的工作线程来进行并发操作,并且可以避免频繁地创建和销毁线程所带来的开销。在线程池中提交的任务会被放入队列等待可用线程处理。这种方式提高了系统的性能并降低了资源消耗。 #### 主要优点包括: - **减少系统负载**: 避免因不断新建线程而导致过多上下文切换。 - **提高响应速度**: 提前准备好了空闲线程可以直接拿来使用,无需等待新线程启动的时间。 - **易于控制**: 可以限制同时运行的最大线程数等配置项以便更好地利用 CPU 和内存资源。 --- ### 进程状态 操作系统中的每个进程都有一个当前的状态描述其活动情况。常见的几种基本状态如下: 1. **就绪态 (Ready)** - 已加载到主存准备好被执行但是还没有获取CPU使用权; 2. **运行态 (Running)** - 正占用处理器执行指令序列期间所处状况; 3. **阻塞态 / 等待态 (Blocked/Wating)** - 因某种原因暂时无法继续执行而挂起,比如I/O请求未完成或者其他同步事件发生;此时不会被调度程序选作下一个执行者直到解除条件消失为止; 4. **终止态 (Terminated/Zombie for Unix-like systems)** - 完成所有任务后的最终阶段,在某些平台如Linux上结束之后会变成僵尸(Zombie)状态直至父进程回收相关信息. --- ### Qt 中的 QThreadPool 类及其应用 Qt是一个跨平台的应用开发框架,QThreadPool作为其中一部分专门负责简化异步计算任务分发给工作者线程的过程.QThread是另一个常用的类但它更侧重于单独创建单个可定制化的线程;相反QThreadPool则是为了高效复用多个通用型后台工作人员设计出来的工具集之一. 当您想要在一个大型GUI项目里安全可靠又简单方便地实施多核运算时,就可以考虑采用这个方案了: ```cpp // 创建全局静态线程池实例(或局部) QThreadPool *globalInstance = new QThreadPool(this); int maxThreadsCount=8; globalInstance->setMaxThreadCount(maxThreadsCount); // 封装具体的业务逻辑函数为Runnable对象 class Task : public QRunnable { protected: void run() override { /* 实现具体任务 */ } }; // 执行任务 Task* task=new Task(); globalInstance->start(task); // 放入线程池开始异步执行 ``` 以上代码片段展示了怎样声明并初始化好最大容量限度内的共享式线程集合体(QThreadPool),然后把自定义的任务单元封装进QRunnable派生出的新类型里面最后交给前者去实际运作起来.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值