Qt多线程的实现方式有: 1。继承QThread类,重写run()方法 2。使用moveToThread将一个继承QObject的子类移至线程,内部槽函数均在线程中执行 3。使用QThreadPool,搭配QRunnable(线程池) 4。使用QtConcurrent(线程池) 为什么要用线程池? 创建和销毁线程需要和OS交互,少量线程影响不大,但是线程数量太大,势必会影响性能,使用线程池可以减少这种开销。 一、继承QThread类,重写run()方法 缺点: 1。每次新建一个线程都需要继承QThread,实现一个新类,使用不太方便。 2。要自己进行资源管理,线程释放和删除。并且频繁的创建和释放会带来比较大的内存开销。 适用场景:QThread适用于那些常驻内存的任务。1mythread。h2ifndefMYTHREADH3defineMYTHREADH45includeQThread67classMyThread:publicQThread8{9public:10MyThread();11voidstop();1213protected:14voidrun();1516private:17volatileboolstopped;18};1920endifMYTHREADH1mythread。cpp2includemythread。h3includeQDebug4includeQString56MyThread::MyThread()7{8stoppedfalse;9}10111213voidMyThread::stop()14{15stoppedtrue;16}17181920voidMyThread::run()21{22qreali0;2324while(!stopped)25{26qDebug()QString(inMyThread:1)。arg(i);27sleep(1);28i;29}30stoppedfalse;31}1widget。h2ifndefWIDGETH3defineWIDGETH45includeQWidget6includemythread。h789QTBEGINNAMESPACE10namespaceUi{classWidget;}11QTENDNAMESPACE1213classWidget:publicQWidget14{15QOBJECT1617public:18Widget(QWidgetparentnullptr);19Widget();2021privateslots:22voidonstartButclicked();2324voidonstopButclicked();2526private:27Ui::Widgetui;28MyThreadthread;29};30endifWIDGETH1widget。cpp23includewidget。h4includeuiwidget。h56Widget::Widget(QWidgetparent)7:QWidget(parent)8,ui(newUi::Widget)9{10uisetupUi(this);11uistartButsetEnabled(true);12uistopButsetEnabled(false);13}1415Widget::Widget()16{17deleteui;18}192021voidWidget::onstartButclicked()22{23thread。start();24uistartButsetEnabled(false);25uistopButsetEnabled(true);26}2728voidWidget::onstopButclicked()29{30if(thread。isRunning())31{32thread。stop();33uistartButsetEnabled(true);34uistopButsetEnabled(false);35}36} 二、使用moveToThread将一个继承QObject的子类移至线程 更加灵活,不需要继承QThread,不需要重写run方法,适用于复杂业务的实现。 注意,该业务类的不同槽函数均在同一个线程中执行。1worker。h2ifndefWORKERH3defineWORKERH45includeQObject67classWorker:publicQObject8{9QOBJECT1011public:12Worker();1314Worker();1516publicslots:17voiddoWork();1819voidanother();2021signals:22voidstopWork();2324};2526endifWORKERH1worker。cpp2includeworker。h3includeQDebug4includeQThread56Worker::Worker()7{89}101112Worker::Worker()13{1415}161718voidWorker::doWork()19{20qDebug()currentthreadidisQThread::currentThreadId();21emitstopWork();22}232425voidWorker::another()26{27qDebug()anothercurrentthreadidisQThread::currentThreadId();28emitstopWork();29}1dialog。h2ifndefDIALOGH3defineDIALOGH45includeQDialog6includeQThread7includeworker。h89QTBEGINNAMESPACE10namespaceUi{classDialog;}11QTENDNAMESPACE1213classDialog:publicQDialog14{15QOBJECT1617public:18Dialog(QWidgetparentnullptr);19Dialog();2021signals:22voidstartWork();23voidstartAnother();2425publicslots:26voidendThread();2728private:29Ui::Dialogui;30QThreadmpThread;31WorkermpWorker;32};33endifDIALOGH1dialog。cpp2includedialog。h3includeuidialog。h4includeQDebug56Dialog::Dialog(QWidgetparent)7:QDialog(parent)8,ui(newUi::Dialog)9{10uisetupUi(this);1112mpThreadnewQThread();13mpWorkernewWorker();1415connect(this,Dialog::startWork,mpWorker,Worker::doWork);16connect(this,Dialog::startAnother,mpWorker,Worker::another);17connect(mpWorker,Worker::stopWork,this,Dialog::endThread);18mpWorkermoveToThread(mpThread);19mpThreadstart();20emitstartWork();21emitstartAnother();22}2324Dialog::Dialog()25{26deleteui;27deletempThread;28deletempWorker;29}303132voidDialog::endThread()33{34qDebug()endThread;35mpThreadquit();36mpThreadwait();37} 不过我为什么要用界面类呢?搞不懂! 三、使用QThreadPool,搭配QRunnable QRunnable常用接口: boolQRunnable::autoDelete()const; voidQRunnable::setAutoDelete(boolautoDelete);QRunnable常用函数不多,主要设置其传到底给线程池后,是否需要自动析构;若该值为false,则需要程序员手动析构,要注意内存泄漏; QThreadPool常用接口: voidQThreadPool::start(QRunnablerunnable,intpriority0); boolQThreadPool::tryStart(QRunnablerunnable);start()预定一个线程用于执行QRunnable接口,当预定的线程数量超出线程池的最大线程数后,QRunnable接口将会进入队列,等有空闲线程后,再执行;priority指定优先级tryStart()和start()的不同之处在于,当没有空闲线程后,不进入队列,返回false 业务类需要继承QRunnable,并且重写run()方法。注意,QRunnbale不是QObject的子类,可以发射信号,但用不了槽函数。 优点:无需手动释放资源,QThreadPool启动线程执行完成后会自动释放。 缺点:不能使用信号槽与外界通信。 适用场景:QRunnable适用于线程任务量比较大,需要频繁创建线程。QRunnable能有效减少内存开销1myrunnable。h2ifndefMYRUNNABLEH3defineMYRUNNABLEH45includeQRunnable6includeQString789classMyRunnable:publicQRunnable10{11public:12MyRunnable(constQStringszThreadName);13voidrun();1415private:16QStringmszThreadName;17};1819endifMYRUNNABLEH1myrunnable。cpp2includemyrunnable。h3includeQDebug4includeQThread56MyRunnable::MyRunnable(constQStringszThreadName):mszThreadName(szThreadName)7{89}101112voidMyRunnable::run()13{14qDebug()Startthreadid:QThread::currentThreadId();15intiCount0;1617while(1)18{19if(iCount10)20{21break;22}2324qDebug()mszThreadNamecount:iCount;25QThread::msleep(500);26}27}1mian。cpp2includeQCoreApplication3includemyrunnable。h4includeQThreadPool56staticQThreadPoolgpThreadPoolNULL;78intmain(intargc,charargv〔〕)9{10QCoreApplicationa(argc,argv);1112MyRunnablepRunnable1newMyRunnable(1thread);13pRunnable1setAutoDelete(true);1415MyRunnablepRunnable2newMyRunnable(2thread);16pRunnable2setAutoDelete(true);1718gpThreadPoolQThreadPool::globalInstance();1920gpThreadPoolstart(pRunnable1);21gpThreadPoolstart(pRunnable2);2223gpThreadPoolNULL;2425returna。exec();26} 四、使用QtConcurrent Concurrent是并发的意思,QtConcurrent是一个命名空间,提供了一些高级的API,使得在编写多线程的时候,无需使用低级线程原语,如读写锁,等待条件或信号。使用QtConcurrent编写的程序会根据可用的处理器内核数自动调整使用的线程数。这意味着今后编写的应用程序将在未来部署在多核系统上时继续扩展。 QtConcurrent::run能够方便快捷的将任务丢到子线程中去执行,无需继承任何类,也不需要重写函数,使用非常简单。 QtConcurrent常用接口: QFutureTQtConcurrent::run(Functionfunction,。。。) QFutureTQtConcurrent::run(QThreadPoolpool,Functionfunction,。。。) 需要在pro文件中添加:QTconcurrent1main。cpp2includeQCoreApplication3includeQThread4includeQThreadPool5includeQtConcurrentQtConcurrent6includeQDebug7includeQFuture89staticQThreadPoolgpThreadPoolQThreadPool::globalInstance();1011classHELLO12{13public:14QStringhello(QStringszName)15{16qDebug()HelloszNamefromQThread::currentThreadId();17returnszName;18}1920voidrun()21{22QFutureQStringf3QtConcurrent::run(this,HELLO::hello,QString(Lily));23QFutureQStringf4QtConcurrent::run(gpThreadPool,this,HELLO::hello,QString(Sam));2425f3。waitForFinished();26f4。waitForFinished();2728qDebug()f3:f3。result();29qDebug()f4:f4。result();30}31};3233QStringhello(QStringszName)34{35qDebug()HelloszNamefromQThread::currentThreadId();36returnszName;37}3839intmain(intargc,charargv〔〕)40{41QCoreApplicationa(argc,argv);4243QFutureQStringf1QtConcurrent::run(hello,QString(Alice));44QFutureQStringf2QtConcurrent::run(gpThreadPool,hello,QString(Bob));4546f1。waitForFinished();47f2。waitForFinished();4849qDebug()f1:f1。result();50qDebug()f2:f2。result();5152HELLOh;53h。run();5455gpThreadPoolNULL;5657returna。exec();58}