C++11消息队列 + Qt线程池 + QRunnable执行任务简单模型
Posted judes
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++11消息队列 + Qt线程池 + QRunnable执行任务简单模型相关的知识,希望对你有一定的参考价值。
1、模板类queue,包含头文件<queue>中,是一个FIFO队列。
queue.push():在队列尾巴增加数据
queue.pop():移除队列头部数据
queue.font():获取队列头部数据的引用
...
2、Qt库的线程池,QThreadPool
QThreadPool.setMaxThreadCount():设置线程池最大线程数 QThreadPool.start(new QRunnable(..)):开启线程池调用QRunnable
3、QRunnable执行任务
void run();//重写虚函数,在里面消费任务队列 setAutoDelete(true)//默认就是true,消费结束自动回收内存
4、代码
run.h
#ifndef RUN_H #define RUN_H #include <QObject> #include <QRunnable> #include <string> #include <iostream> struct MyString std::string valueStr; ; class Run : public QObject , public QRunnable Q_OBJECT public: Run() = default; Run(const MyString& myString); protected: ~Run() = default; void run(); signals: public slots: private: MyString myString; ; #endif // RUN_H
说明:MyString结构体代替实际项目中的任务,Run接口的run纯虚函数用来消费分配来的MyString
run.cpp
#include "run.h" #include <QThread> #include <QDebug> Run::Run(const MyString &myString) this->myString = myString; //this->setAutoDelete(true);//默认就是true void Run::run() //std::cout << "value:" << this->myString.valueStr <<";调用线程ID为:" << QThread::currentThread() << std::endl; qDebug() << "value:" << QString::fromStdString(myString.valueStr) << "thread:" << QThread::currentThreadId(); QThread::msleep(100);
说明:不使用cout打印是因为,cout打印不是原子操作,可能多个字符串被杂糅在一起打印;qDebug不会,应该底层加了锁
main.cpp
#include <QCoreApplication> #include "run.h" #include <queue> #include <mutex> #include <QThreadPool> #include <thread> using namespace std; queue<MyString> myList; mutex myMutex; volatile bool addThreadIsEnd = false; void makeListThread(); int main(int argc, char *argv[]) QCoreApplication a(argc, argv); cout << "begin main" << endl; thread addThread(makeListThread); addThread.detach(); cout << "begin addThread" << endl; QThreadPool tp; tp.setMaxThreadCount(20); cout << "begin threadPool" << endl; while(true) if(!myList.empty()) MyString tempMyString = myList.front(); tp.start(new Run(tempMyString)); myMutex.lock(); myList.pop(); myMutex.unlock(); else if(addThreadIsEnd) break; else QThread::msleep(10); cout << "end main,list size:" << myList.size() << endl; return a.exec(); void makeListThread() string a; MyString tempMyString; for(int i=0;i<10000;i++) QThread::msleep(0); a = to_string(i); tempMyString.valueStr = a; myMutex.lock(); myList.push(tempMyString); myMutex.unlock(); addThreadIsEnd = true; cout << "end addThread" << endl;
5、模型
6、其他说明
6.1、假设线程池大小有n个,那么这n个线程在线程池初始化的时候就已经定了,即n个线程id是恒定的,队列永远由这n个线程消费
6.2、std::queue非线程安全,同时往队列加任务、取任务可能会触发线程安全问题;同时删除头任务、访问头任务也可能会触发线程安全问题,需要加线程锁
6.3、tp.start(new Run(tempMyString));这里new了一个没有指针指向的Runnable对象,在哪里回收的呢?Run.setAutoDelete(true)自动回收
以上是关于C++11消息队列 + Qt线程池 + QRunnable执行任务简单模型的主要内容,如果未能解决你的问题,请参考以下文章
如何并行运行 Qt GUI 和 Linux 消息队列接收线程?