您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > QT5开发与实例第12章Qt5多线程.
第12章Qt5多线程12.1多线程的简单实现12.2多线程控制12.3多线程应用的例子12.1多线程的简单实现(1)在头文件“threaddlg.h”中声明用于界面显示所需的控件,其具体代码如下:#includeQDialog#includeQPushButtonclassThreadDlg:publicQDialog{Q_OBJECTpublic:ThreadDlg(QWidget*parent=0);~ThreadDlg();private:QPushButton*startBtn;QPushButton*stopBtn;QPushButton*quitBtn;};12.1多线程的简单实现(2)在源文件“threaddlg.cpp”的构造函数中,完成各个控件的初始化工作,其具体代码如下:#includethreaddlg.h#includeQHBoxLayoutThreadDlg::ThreadDlg(QWidget*parent):QDialog(parent){setWindowTitle(tr(线程));startBtn=newQPushButton(tr(开始));stopBtn=newQPushButton(tr(停止));quitBtn=newQPushButton(tr(退出));QHBoxLayout*mainLayout=newQHBoxLayout(this);mainLayout-addWidget(startBtn);mainLayout-addWidget(stopBtn);mainLayout-addWidget(quitBtn);}12.1多线程的简单实现(3)此时运行程序,界面显示如图12.1所示。12.1多线程的简单实现以上完成了界面的设计,下面的内容是具体的功能实现。(1)在头文件“workthread.h”中,工作线程WorkThread类继承自QThread类。重新实现run()函数。其具体代码如下:#includeQThreadclassWorkThread:publicQThread{Q_OBJECTpublic:WorkThread();protected:voidrun();};12.1多线程的简单实现(2)在源文件“workthread.cpp”中添加具体实现代码如下:#includeworkthread.h#includeQtDebugWorkThread::WorkThread(){}run()函数实际上是一个死循环,它不停地打印数字0~9。为了显示效果明显,程序将每一个数字重复打印8次。voidWorkThread::run(){while(true){for(intn=0;n10;n++)qDebug()nnnnnnnn;}}12.1多线程的简单实现(3)在头文件“threaddlg.h”中添加以下内容:#includeworkthread.h#defineMAXSIZE1publicslots:voidslotStart();voidslotStop();private:WorkThread*workThread[MAXSIZE];12.1多线程的简单实现(4)在源文件“threaddlg.cpp”中添加以下内容:其中,在构造函数中添加如下代码:connect(startBtn,SIGNAL(clicked()),this,SLOT(slotStart()));connect(stopBtn,SIGNAL(clicked()),this,SLOT(slotStop()));connect(quitBtn,SIGNAL(clicked()),this,SLOT(close()));槽函数slotStart(),当用户单击“开始”按钮时,此函数将被调用。这里使用两个循环,目的是为了使新建的线程尽可能同时开始执行,其具体实现代码如下:voidThreadDlg::slotStart(){for(inti=0;iMAXSIZE;i++){workThread[i]=newWorkThread();}for(inti=0;iMAXSIZE;i++){workThread[i]-start();}startBtn-setEnabled(false);stopBtn-setEnabled(true);}12.1多线程的简单实现槽函数slotStop(),当用户单击“停止”按钮时,此函数将被调用。其具体实现代码如下:voidThreadDlg::slotStop(){for(inti=0;iMAXSIZE;i++){workThread[i]-terminate();workThread[i]-wait();}startBtn-setEnabled(true);stopBtn-setEnabled(false);}12.1多线程的简单实现(5)运行结果如图12.2所示。12.2多线程控制下面举一个例子来说明问题:classKey{public:Key(){key=0;}intcreatKey(){++key;returnkey;}intvalue()const{returnkey;}private:intkey;};12.2多线程控制虽然类Key产生主键的函数creatKey()只有一条语句执行修改成员变量key的值,但是C++的“++”操作符并不是原子操作,通常编译后它将被展开成为以下三条机器命令:将变量值载入寄存器;将寄存器中的值加1;将寄存器中的值写回主存。12.2.1互斥量1.QMutex类QMutex类还提供了一个tryLock()函数,如果互斥量已被锁定,则立即返回。例如:classKey{public:Key(){key=0;}intcreatKey(){mutex.lock();++key;returnkey;mutex.unlock();}intvalue()const{mutex.lock();returnkey;mutex.unlock();}private:intkey;QMutexmutex;};12.2.1互斥量2.QMutexLocker类例如:classKey{public:Key(){key=0;}intcreatKey(){QMutexLocker.locker(&mutex);++key;returnkey;}intvalue()const{QMutexLocker.locker(&mutex);returnkey;}private:intkey;QMutexmutex;};12.2.2信号量生产者/消费者实例中对同步的需求有两处:(1)如果生产者过快地生产数据,将会覆盖消费者还没有读取的数据。(2)如果消费者过快地读取数据,将越过生产者并且读取到一些过期数据。针对以上问题,可以有两种解决方法:(1)首先使生产者填满整个缓冲区,然后等待消费者读取整个缓冲区,这是一个比较笨拙的方法。(2)使生产者和消费者线程同时分别操作缓冲区的不同部分,这是一种比较高效的方法。12.2.2信号量(1)源文件“main.cpp”中添加的具体实现代码如下:#includeQCoreApplication#includeQSemaphore#includeQThread#includestdio.hconstintDataSize=1000;constintBufferSize=80;intbuffer[BufferSize];QSemaphorefreeBytes(BufferSize);QSemaphoreusedBytes(0);12.2.2信号量(2)Producer类继承自QThread类,作为生产者类,其声明如下:classProducer:publicQThread{public:Producer();voidrun();};Producer构造函数中没有实现任何内容:Producer::Producer(){}12.2.2信号量Producer::run()函数的具体实现代码如下:voidProducer::run(){for(inti=0;iDataSize;i++){freeBytes.acquire();buffer[i%BufferSize]=(i%BufferSize);usedBytes.release();}}12.2.2信号量(3)Consumer类继承自QThread类,作为消费者类,其声明如下:classConsumer:publicQThread{public:Consumer();voidrun();};Consumer构造函数中没有实现任何内容:Consumer::Consumer(){}12.2.2信号量Consumer::run()函数的具体实现代码如下:voidConsumer::run(){for(inti=0;iDataSize;i++){usedBytes.acquire();fprintf(stderr,%d,buffer[i%BufferSize]);if(i%16==0&&i!=0)fprintf(stderr,\n);freeBytes.release();}fprintf(stderr,\n);}12.2.2信号量(4)main()函数的具体内容如下:intmain(intargc,char*argv[]){QCoreApplicationa(argc,argv);Producerproducer;Consumerconsumer;producer.start();consumer.start();producer.wait();consumer.wait();returna.exec();}12.2.2信号量(5)最终运行结果如图12.3所示。12.2.3线程等待与唤醒源文件“main.cpp”的具体内容如下:#includeQCoreApplication#includeQWaitCondition#includeQMutex#includeQThread#includestdio.hconstintDataSize=1000;constintBufferSize=80;intbuffer[BufferSize];QWaitConditionbufferEmpty;QWaitConditionbufferFull;QMutexmutex;intnumUsedBytes=0;intrIndex=0;12.2.3线程等待与唤醒生产者线程Producer类继承自QThread类,其声明如下:classProducer:publicQThread{public:Producer();voidrun();};Producer构造函数无须实现:Producer::Producer(){}12.2.3线程等待与唤醒Producer::run()函数的具体内容如下:voidProducer::run(){for(inti=0;iDataSize;i++){mutex.lock();if(numUsedBytes==BufferSize)bufferEmpty.wait(&mutex);buffer[i%BufferSize]=numUsedBytes;++numUsedBytes;bufferFull.wakeAll();mutex.unlock();}}12.2.3线程等待与唤醒消费者线程Consumer类继承自QThread类,其声明如下:classConsumer:publicQThread{public:Consumer();voidrun();};Consumer构造函数中无须实现内容:Consumer::Consumer(){}12.2.3线程等待与唤醒Consumer::run()函数的具体内容如下:voidConsumer::run(){forever{m
本文标题:QT5开发与实例第12章Qt5多线程.
链接地址:https://www.777doc.com/doc-2854592 .html