一、想要使用Qthread必须先创建,继承Qthread的类。
1 #ifndef THREADTEST_H 2 #define THREADTEST_H 3 4 #include <QThread> 5 #include <QMutex> 6 7 class ThreadTest : public QThread 8 { 9 public: 10 ThreadTest(); 11 ~ThreadTest(); 12 13 void setMessage(const QString &message); 14 void stop(); 15 16 protected: 17 void run() Q_DECL_OVERRIDE; 18 19 20 private: 21 QString messageStr; 22 volatile bool stopped; 23 QMutex mutex; 24 bool quit; 25 26 }; 27 28 #endif // THREADTEST_H
创建的类中有void run()函数和void stop()。
当调用start()函数时,会接着调用run函数。
二、Mutex互斥锁
可以用mutex.lock()上锁,mutex.unlock()解锁。用以保护资源。
然后可以用简化的方式使用QmutexLocker lock(&mutex),函数中部分结束后自动释放。
还有QReadWriteLock来替换mutex。lock.lockForRead(),lock.lockForWrite()
三、信号量
QSemaphore semaphore(1);
semaphore.acquire();
semaphore.release();
信号量和互斥量的区别在于信号量可以设置初值。
四、在生产和消费中的应用。
freeSpace.acquire();
写
freeSpace.realease();
usedSpace.acquire();
读
usedSpcae.release();
五、QWaitCondition
QWaitCondition允许一个线程在满足一定的条件下触发其他多个线程。可以和QMutex一起使用达到精确控制。
不同的消息就要用到不同的QWaitCondition,传入的参数必须是锁定的mutex。
#include <iostream> #include <QtCore> using namespace std; const int DataSize = 200; const int BufferSize = 10; int buffer[BufferSize]; int usedSpace = 0; QMutex mutex; QWaitCondition bufferIsNotEmpty; QWaitCondition bufferIsNotFull; class Producer : public QThread { void run(); }; void Producer::run() { for(int i =0;i<DataSize;i++) { mutex.lock(); if(usedSpace == BufferSize) bufferIsNotFull.wait(&mutex); buffer[i%BufferSize] = i; std::cerr<<"P"; usedSpace++; bufferIsNotEmpty.wakeAll(); mutex.unlock(); } } class Consumer : public QThread { void run(); }; void Consumer::run() { for(int i =0;i<DataSize;i++) { mutex.lock(); if(usedSpace == 0) bufferIsNotEmpty.wait(&mutex); usedSpace--; std::cerr<<buffer[i%BufferSize]<<" "; bufferIsNotFull.wakeAll(); mutex.unlock(); } } int main() { Producer producer; Consumer consumer; producer.start(); consumer.start(); producer.wait(); consumer.wait(); return 0; }
用QSemaphore也可以实现
const int DataSize = 100000; const int BufferSize = 8192; char buffer[BufferSize]; QSemaphore freeBytes(BufferSize); QSemaphore usedBytes; class Producer : public QThread { public: void run(); }; void Producer::run() { qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); for (int i = 0; i < DataSize; ++i) { freeBytes.acquire(); buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4]; usedBytes.release(); } } class Consumer : public QThread { public: void run(); }; void Consumer::run() { for (int i = 0; i < DataSize; ++i) { usedBytes.acquire(); fprintf(stderr, "%c", buffer[i % BufferSize]); freeBytes.release(); } fprintf(stderr, " "); } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); Producer producer; Consumer consumer; producer.start(); consumer.start(); producer.wait(); consumer.wait(); return 0; }
六、而Main和次线程通信
要是实现这个功能可以用信号和槽机制
在主界面中运行创建一个Thread *mythread指针,然后mythread->start();不会出错。