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、Qt多线程(QThread)
Qt多线程是指在Qt框架中使用线程(Thread)来实现并发执行的技术。Qt提供了一套完整的多线程支持,使得开发者能够创建和管理线程,以提高应用程序的性能和响应性。以下是一些关键的技术点:
1. QThread 类:
- Qt中的线程是通过继承自QThread的类来实现的。
- 使用QThread可以创建线程,启动线程执行,以及控制线程的运行。
2. 事件循环:
- 每个线程可以有自己的事件循环,通过QThread::exec()启动。
- 事件循环允许线程接收和处理事件,例如定时器事件、信号等。
3. 线程安全:
- 多线程编程中,线程安全是一个重要的考虑因素。
- Qt提供了多种机制来确保线程安全,例如QMutex、QReadWriteLock、QSemaphore等。
4. 信号和槽:
- Qt的信号和槽机制支持跨线程通信。
- 使用Qt::QueuedConnection可以安全地在不同线程之间传递信号和槽。
5. 局部对象:
- 在线程中创建的局部对象,如QMutexLocker,可以自动管理锁的获取和释放。
6. 线程池:
- Qt提供了QThreadPool,用于管理一组可重用的线程。
- 线程池可以提高资源利用率,避免频繁创建和销毁线程。
7. 线程间数据共享:
- 使用QSharedMemory可以安全地在线程间共享数据。
- 共享内存需要正确的同步机制来避免竞态条件。
8. 线程间同步:
- 使用QWaitCondition可以等待某个条件成立。
- 结合QMutex使用,可以实现线程间的同步。
9. 线程生命周期管理:
- 通过QThread::quit()和QThread::terminate()可以控制线程的退出。
- 使用QThread::finished()信号可以知道线程何时结束。
10. 线程优先级:
- 可以通过QThread::setPriority()设置线程的优先级。
11. 线程局部存储:
- 使用QThreadStorage可以为每个线程创建独立的局部存储。
12. 线程安全的数据容器:
- Qt提供了线程安全的数据容器,如QQueue、QStack、QLinkedList等。
13. 线程的创建和销毁:
- 线程的创建通过QThread的构造函数和start()方法。
- 线程的销毁需要确保线程已经安全退出,可以通过wait()方法等待线程结束。
14. 线程的异常处理:
- 需要考虑线程中的异常处理,确保线程异常不会影响整个应用程序的稳定性。
15. 线程的调试和诊断:
- 使用Qt的调试工具和日志系统可以帮助诊断多线程程序中的问题。
使用Qt进行多线程编程时,需要仔细设计线程的创建、同步、通信和销毁过程,以确保程序的稳定性和效率。同时,要注意避免常见的多线程问题,如死锁、竞态条件等。