QThread类提供了管理线程的方法:
一个对象管理一个线程 一般从QThread继承一个自定义类,重载run函数 
 
 
class DiceThread :  public QThread
{ Q_OBJECTprivate:int m_seq =  0 ; int m_diceValue; bool m_Paused =  true ; bool m_stop =  false ; public:explicit DiceThread( ) ; void diceBegin( ) ; void dicePause( ) ; void stopThread( ) ; protected:void run( )  Q_DECL_OVERRIDE; signals:void newValued( int seq, int diceValue) ; public slots:
} ; 
DiceThread::DiceThread ( ) 
{ } void DiceThread::diceBegin ( ) 
{ m_Paused =  false ; 
} void DiceThread::dicePause ( ) 
{ m_Paused =  true ; 
} void DiceThread::stopThread ( ) 
{ m_stop =  true ; 
} void DiceThread::run ( ) 
{ m_stop =  false ; m_seq =  0 ; qsrand( QTime::currentTime( ) .second( )) ; while  ( ! m_stop)  { if( ! m_Paused) { m_diceValue =  qrand( ) %6+1; m_seq++; emit newValued( m_seq, m_diceValue) ; } sleep( 1 ) ; } quit( ) ; 
} 
Dialog::Dialog( QWidget *parent)  : QDialog( parent) ,ui( new Ui::Dialog) 
{ ui-> setupUi( this) ; ui-> btnStartThread-> setEnabled( true) ; ui-> btnStart-> setEnabled( false) ; ui-> btnStop-> setEnabled( false) ; ui-> btnStopThread-> setEnabled( false) ; connect( & threadA, SIGNAL( started( )) ,this, SLOT( on_threadAStarted( )) ) ; connect( & threadA, SIGNAL( finished( )) ,this, SLOT( on_threadAFinished( )) ) ; connect( & threadA, SIGNAL( newValued( int,int)) ,this, SLOT( on_threadAnewValue( int,int)) ) ; 
} Dialog::~Dialog ( ) 
{ delete ui; 
} void Dialog::closeEvent( QCloseEvent *event) 
{ if( threadA.isRunning( )) { threadA.stopThread( ) ; threadA.wait( ) ; } event-> accept( ) ; 
} void Dialog::on_btnStartThread_clicked ( ) 
{ threadA.start( ) ; 
} void Dialog::on_btnStart_clicked ( ) 
{ threadA.diceBegin( ) ; 
} void Dialog::on_btnStop_clicked ( ) 
{ threadA.dicePause( ) ; 
} void Dialog::on_btnStopThread_clicked ( ) 
{ threadA.stopThread( ) ; 
} void Dialog::on_btnClearText_clicked ( ) 
{ ui-> plainTextEdit-> clear( ) ; 
} void Dialog::on_threadAnewValue( int seq, int diceValue) 
{ ui-> plainTextEdit-> appendPlainText( QString::asprintf( "第%d次投色子: 点数%d" , seq, diceValue)) ; 
} void Dialog::on_threadAStarted ( ) 
{ ui-> labelStatus-> setText( "Thread状态:started" ) ; ui-> btnStartThread-> setEnabled( false) ; ui-> btnStart-> setEnabled( true) ; ui-> btnStop-> setEnabled( true) ; ui-> btnStopThread-> setEnabled( true) ; 
} void Dialog::on_threadAFinished ( ) 
{ ui-> labelStatus-> setText( "Thread状态:finished" ) ; ui-> btnStartThread-> setEnabled( true) ; ui-> btnStart-> setEnabled( false) ; ui-> btnStop-> setEnabled( false) ; ui-> btnStopThread-> setEnabled( false) ; 
} 
 
QMutex和QMutexLocker是基于互斥量的线程同步类
QMutex定义的实力是互斥量,主要提供了三个函数 lock():锁定互斥量,如果另一个线程锁定了这个互斥量,将阻塞直到另一个解锁 unlock():解锁一个互斥量 trylock():尝试锁定一个互斥量,如果成功返回true,失败(其他线程已经锁定这个互斥量)返回false,不阻塞线程。  QMutexLocker简化了互斥量的处理 构造一个函数接受一个互斥量作为参数,并将其锁定 析构函数解锁该互斥量  void DiceThread::readValue( int *seq, int *diceValue) 
{ *seq =  m_seq; *diceValue =  m_diceValue; 
} void DiceThread::run ( ) 
{ m_stop =  false ; m_seq =  0 ; qsrand( QTime::currentTime( ) .second( )) ; while  ( ! m_stop)  { if( ! m_Paused) { m_diceValue =  50 ; msleep( 50 ) ; m_diceValue =  qrand( ) ; msleep( 50 ) ; m_diceValue =  m_diceValue%6+1; msleep( 50 ) ; m_seq++; 
//            emit newValued( m_seq, m_diceValue) ; } sleep( 1 ) ; } quit( ) ; 
} 
void Dialog::on_TimerOut ( ) 
{ int seq, diceValue; threadA.readValue( & seq, & diceValue) ; ui-> plainTextEdit-> appendPlainText( QString::asprintf( "第%d次投色子: 点数%d" , seq, diceValue)) ; 
} 
 
void DiceThread::readValue( int *seq, int *diceValue) 
{ mMutex.lock( ) ; *seq =  m_seq; *diceValue =  m_diceValue; mMutex.unlock( ) ; 
} void DiceThread::run ( ) 
{ m_stop =  false ; m_seq =  0 ; qsrand( QTime::currentTime( ) .second( )) ; while  ( ! m_stop) { if( ! m_Paused) { mMutex.lock( ) ; m_diceValue =  50 ; msleep( 50 ) ; m_diceValue =  qrand( ) ; msleep( 50 ) ; m_diceValue =  m_diceValue % 6  + 1 ; msleep( 50 ) ; m_seq++; //            emit newValued( m_seq, m_diceValue) ; mMutex.unlock( ) ; } sleep( 1 ) ; } quit( ) ; 
} 
 
void DiceThread::readValue( int *seq, int *diceValue) 
{ QMutexLocker locker( & mMutex) ; *seq =  m_seq; *diceValue =  m_diceValue; 
} 
bool DiceThread::readValue( int *seq, int *diceValue) 
{ //    QMutexLocker locker( & mMutex) ; if( mMutex.tryLock( )) { *seq =  m_seq; *diceValue =  m_diceValue; mMutex.unlock( ) ; return  true ; } return  false ; 
} 
QReadWriteLock提供了以下主要函数:
lockForRead():只读方式锁定资源,如果有其他线程以写入方式锁定,这个函数会阻塞 lockForWrite():以写入方式锁定资源,如果本线程或者其他线程以读取或写入锁定资源,则函数阻塞 unlock():解锁 tryLockForRead():是lockForRead非阻塞版本 tryLockForWrite():是lockForWrite非阻塞版本 读写锁同样有QReadLocker和QWriteLocker QWaitCondition用于通知其他线程,如接收数据和处理数据之间通知。提供了一些函数:
wait(QMutex *lockedMutex):进入等待状态,解锁互斥量lockMutex,被唤醒后锁定lockMutex并退出函数 wakeAll():唤醒所有处于等待的线程,线程唤醒的顺序不确定,有操作系统调度策略决定 QakeOne():唤醒一个处于等待状态的线程,唤醒哪个线程不确定,由操作系统调度策略决定 
 
int m_seq =  0 ; 
int m_diceValue; 
bool m_stop =  false ; 
QMutex m_Mutex; 
QWaitCondition waitCondition; ProducerThread::ProducerThread ( ) 
{ } void ProducerThread::stopThread ( ) 
{ m_stop =  true ; 
} void ProducerThread::run ( ) 
{ m_stop =  false ; m_seq =  0 ; qsrand( QTime::currentTime( ) .second( )) ; while  ( ! m_stop) { m_Mutex.lock( ) ; m_diceValue =  qrand( )  % 6  + 1 ; m_seq++; m_Mutex.unlock( ) ; waitCondition.wakeOne( ) ; sleep( 1 ) ; } quit( ) ; 
} ConsumerThread::ConsumerThread ( ) 
{ } void ConsumerThread::stopThread ( ) 
{ m_stop =  true ; waitCondition.wakeOne( ) ;  // 需要给wait置信号,否则阻塞无法结束
} void ConsumerThread::run ( ) 
{ m_stop =  false ; while  ( ! m_stop) { m_Mutex.lock( ) ; waitCondition.wait( & m_Mutex) ; emit newValued( m_seq, m_diceValue) ; m_Mutex.unlock( ) ; msleep( 100 ) ; } quit( ) ; 
} 
 
QSemaphore信号量通常用于保护一定数量的相同的资源。QSemaphore是实现信号量功能的类,提供了以下函数:
acquire(int n):尝试获得n个资源,如果不够将阻塞线程,直到n个资源可用 release(int n):释放资源,如果资源已经全部可用,则可扩充资源总数 int available():返回房前信号量的资源个数 bool tryAcquire(int n=1):尝试获取n个资源,不成功是,不阻塞线程 
 
 
const int bufferSize =  8 ; 
int buffer1[ bufferSize]  =  { 0 } ; 
int buffer2[ bufferSize]  =  { 0 } ; 
int curBuf =  1 ;  // 当前采集数据使用的缓冲区QSemaphore semEmptyBufs( 2 ) ;  // 两个资源
QSemaphore semFullBufs; ThreadDAQ::ThreadDAQ ( ) 
{ } void ThreadDAQ::stopThread ( ) 
{ m_stop =  true ; 
} void ThreadDAQ::run ( ) 
{ m_stop =  false ; int counter =  0 ; while( ! m_stop) { semEmptyBufs.acquire( ) ; for  ( int i =  0 ;  i <  bufferSize;  ++i) { if( curBuf ==  1 ) { buffer1[ i]  =  counter; } else { buffer2[ i]  =  counter; } counter++; msleep( 50 ) ; } if( curBuf ==  1 ) { curBuf =  2 ; } else { curBuf =  1 ; } semFullBufs.release( ) ; } exit( ) ; 
} ThreadShow::ThreadShow ( ) 
{ } void ThreadShow::stopThread ( ) 
{ m_stop =  true ; 
} void ThreadShow::run ( ) 
{ m_stop =  false ; int seq  =  0 ; while( ! m_stop) { semFullBufs.acquire( ) ; int buf[ bufferSize]  =  { 0 } ; if( curBuf ==  1 ) { memcpy( buf, buffer2, sizeof( int) *bufferSize) ; } else { memcpy( buf, buffer1, sizeof( int) *bufferSize) ; } emit newValue( buf, bufferSize, seq++) ; semEmptyBufs.release( ) ; } exit( ) ; 
} 
Dialog::Dialog( QWidget *parent)  : QDialog( parent) ,ui( new Ui::Dialog) 
{ ui-> setupUi( this) ; ui-> btnStopThread-> setEnabled( false) ; connect( & threadConsumer, SIGNAL( newValue( int*, int, int)) ,this, SLOT( on_threadNewValue( int*, int, int)) ) ; connect( & threadProducer, SIGNAL( started( )) ,this, SLOT( on_threadProducer_started( )) ) ; connect( & threadProducer, SIGNAL( finished( )) ,this, SLOT( on_threadProducer_finished( )) ) ; connect( & threadConsumer, SIGNAL( started( )) ,this, SLOT( on_threadConsumer_started( )) ) ; connect( & threadConsumer, SIGNAL( finished( )) ,this, SLOT( on_threadConsumer_finished( )) ) ; 
} Dialog::~Dialog ( ) 
{ delete ui; 
} void Dialog::on_threadNewValue( int *data, int count, int seq ) 
{ QString str =  QString::asprintf( "第%03d次,内容:" , seq ) ; for  ( int var =  0 ;  var <  count;  ++var) { str +=  QString::asprintf( "%03d ," , data[ var] ) ; } ui-> plainTextEdit-> appendPlainText( str) ; 
} void Dialog::on_btnStartThread_clicked ( ) 
{ threadConsumer.start( ) ; threadProducer.start( ) ; ui-> btnStartThread-> setEnabled( false) ; ui-> btnStopThread-> setEnabled( true) ; 
} void Dialog::on_btnStopThread_clicked ( ) 
{ threadProducer.stopThread( ) ; threadConsumer.stopThread( ) ; ui-> btnStartThread-> setEnabled( true) ; ui-> btnStopThread-> setEnabled( false) ; 
} void Dialog::on_btnClearText_clicked ( ) 
{ ui-> plainTextEdit-> clear( ) ; 
} void Dialog::on_threadProducer_started ( ) 
{ ui-> labelProducer-> setText( "Producer线程:started" ) ; 
} void Dialog::on_threadProducer_finished ( ) 
{ ui-> labelProducer-> setText( "Producer线程:finished" ) ; 
} void Dialog::on_threadConsumer_started ( ) 
{ ui-> labelConsumer-> setText( "Consumer线程:started" ) ; 
} void Dialog::on_threadConsumer_finished ( ) 
{ ui-> labelConsumer-> setText( "Consumer线程:finished" ) ; 
}