Qt 多线程学习
来源:互联网 发布:handler源码解析 编辑:程序博客网 时间:2024/06/11 05:47
最近的项目上用到了关于多线程的知识,自己也比较感兴趣,所以就拿了那本《C++ GUI Qt4 编程》来学习。
这本书的第14章是关于多线程的知识,使用的Qt版本是Qt4.x。在下用的是最新的Qt 5.2,所以代码上有一些不兼容,稍加修改就可以运行了。
Qt的多线程简单来说就是继承QThread类,重载run()函数,start()启动线程。首先来看下书上的第一个例子:(修改版的代码已上传,点击下载)
class Thread : public QThread{ Q_OBJECTpublic: Thread(QString message = "", QObject *parent = NULL); ~Thread(); void setMessage(QString); QString getMessage(); void stop();protected: void run();private: QString message; volatile bool stopped;};
Thread类继承了QThread类,并实现了run函数。stopped变量前面的volatile声明stopped为易失性变量,这样每次读取stopped时都是最新的值。
继续看Thread类的实现:
Thread::Thread(QString message, QObject *parent) : stopped(false) , QThread(parent) , message(message){}Thread::~Thread(){ this->stop(); this->wait(); qDebug() << this;}void Thread::setMessage(QString message){ this->message = message;}QString Thread::getMessage(){ return this->message;}void Thread::stop(){ stopped = true;}void Thread::run(){ while (!stopped) std::cerr << qPrintable(message); stopped = false; std::cerr << std::endl;}
初始化时将stopped设置为false,run函数中持续检查stopped的值,为true时才退出。
Dialog::Dialog(QWidget *parent) : QDialog(parent){ QPushButton *buttonQuit = new QPushButton(QString::fromLocal8Bit("Quit")); connect(buttonQuit, &QPushButton::clicked, this, &Dialog::close); QBoxLayout *layout = new QBoxLayout(QBoxLayout::LeftToRight, this); QStringList list = QString("ABCDEFGHIJKLMN").split("",QString::SkipEmptyParts); foreach (QString name, list) { Thread *thread = new Thread(name, this); QPushButton *button = new QPushButton(QString("Start ")+name, this); mappingTable.insert(button, thread); connect(button, &QPushButton::clicked, this, &Dialog::startOrStopThread); layout->addWidget(button); } layout->addWidget(buttonQuit); this->setLayout(layout);}void Dialog::startOrStopThread(){ QPushButton *buttonNow = dynamic_cast<QPushButton*>(sender()); Thread *threadNow = (Thread*)mappingTable[buttonNow]; if (threadNow == NULL) return; if(threadNow->isRunning()) { threadNow->stop(); buttonNow->setText( buttonNow->text().replace(QString("Stop"),QString("Start")) ); } else { threadNow->start(); buttonNow->setText( buttonNow->text().replace(QString("Start"),QString("Stop")) ); }}
在Dialog界面类中,将button与thread实现一一对应的连接,在槽函数中就可以方便的找到对应的线程了。其中mappingTable是QMap<QObject*, QObject*>类型的。
这样就可以方便的实现多个线程的修改,如下图:
另外,第四个例子对我也很有启发:
TransactionThread::TransactionThread(QObject *parent) : QThread(parent){ start();}TransactionThread::~TransactionThread(){ { QMutexLocker locker(&mutex); while (!transactions.isEmpty()) delete transactions.dequeue(); transactionCondition.wakeOne(); } wait();}void TransactionThread::addTransaction(Transaction *transaction){ QMutexLocker locker(&mutex); transactions.enqueue(transaction); transactionCondition.wakeOne();}void TransactionThread::run(){ Transaction *transaction = 0; QImage oldImage; forever { { QMutexLocker locker(&mutex); if (transactions.isEmpty()) transactionCondition.wait(&mutex); if (transactions.isEmpty()) break; transaction = transactions.dequeue(); oldImage = currentImage; } emit transactionStarted(transaction->message(), 0); QImage newImage = transaction->apply(oldImage); delete transaction; { QMutexLocker locker(&mutex); currentImage = newImage; if (transactions.isEmpty()) emit allTransactionsDone(); } }}void TransactionThread::setImage(const QImage& image){ QMutexLocker locker(&mutex); currentImage = image;}QImage TransactionThread::getImage(){ QMutexLocker locker(&mutex); return currentImage;}
以上为线程实现的关键代码。在读取和写入从线程与主线程共享的变量时,都要使用mutex互斥变量。使用QMutexLocker locker(&mutex)也更方便,在构造是lock,析构时unlock,临时变量超过了作用域自然被析构,不得不说实现者的方法很巧妙啊。至于transactionCondition.wait(&mutex)则是等待条件。当事务队列为空时,等待事务加入,或者析构。加入事务时唤醒即可,即transactionCondition.wakeOne()。
- Qt多线程学习:创建多线程
- Qt多线程学习:创建多线程
- Qt多线程学习:创建多线程
- Qt多线程学习:创建多线程
- Qt多线程学习:创建多线程
- Qt多线程学习:创建多线程
- Qt多线程学习 ( 2 )
- QT多线程的学习
- Qt多线程学习
- Qt 多线程学习
- Qt多线程学习
- Qt 多线程学习
- Qt 多线程学习(1)
- Qt学习 之 多线程程序设计
- QT学习笔记18多线程
- 浅谈 Qt 多线程类 起点学习
- Qt学习笔记(十)多线程
- [Qt学习篇]Qthread实现多线程操作
- Android上传图片到服务器上的一些问题
- HDU4893 2014多校第三场1007 Wow! Such Sequence!
- hdoj.1256 画8 20140726
- 数据的交换输出
- rysnc和intotify实现数据同步
- Qt 多线程学习
- 如何用Tomcat和Openssl构建HTTPS双向认证环境(HTTPS客户端认证)
- iOS开发笔记之五——Xcode 6.0 Beta编译工程时可能遇到的问题及参考解决方案
- leetcode Plus One
- 判断是不是IE的js代码
- coco2dx 3.0以后最box2d和chipmunk这两个物理引擎进行了封装,使用起来非常的便利。
- 数组运用-1075
- mybatis在xml文件中处理大于号小于号的方法
- Hive操作语句的使用实例讲解