线程
①、就绪状态 :
线程一旦被new Thread 创建之后,就会立刻进入(RUnnable)就绪状态,因为CPU资源十分宝贵,所以需要等待CPU资源。
②、运行状态:
当该线程枪战到CPU资源后,就会立刻进入执行状态
③、阻塞状态
如果遇到sleep()或者IO阻塞,则会进入阻塞状态,当sleep()时间到了或者IO阻塞返回获得同步锁,则再次进入就绪状态
sleep():使得线程在指定的时间内进入阻塞状态,不能得到CPU资源,且不会释放锁资源,时间一过,就会立刻进入就绪状态
wait():使得线程进入阻塞状态,释放所资源,和notify()搭配使用
④、死亡状态:
(1)、run()方法正常退出,线程自然死亡
(2)、一个未捕获的异常,终止了线程,使得线程异常死亡
线程池
1.1、线程池(QThreadPool)管理并重新设置单个QThread对象的样式,以帮助减少使用线程的程序中的线程创建成本。每个Qt应用程序都有一个全局QThreadPool对象,可以通过调用globalInstance()来访问该对象。
1.2、要使用QThreadPool线程之一,请将QRunnable子类化并实现run()虚拟函数。然后创建该类的对象并将其传递给QThreadPool::start()。
1.3、默认情况下,QThreadPool会自动删除QRunnable。使用qrunable::setAutoDelete()更改自动删除标志。
1.4、线程池可以维护线程数据,如果需要多线程执行任务时,只要将任务的指令传递给线程池即可,线程池会根据可用线程进行安排。
1.5、线程池可以防止线程之间资源竞争
多线程
2.1、多线程的创建及销毁,需要频繁的系统交互,会产生很大开销,若频繁的创建线程,建议使用线程池。
.cpp文件#include \"mainwindow.h\"#include \"ui_mainwindow.h\"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow){ui->setupUi(this);myThreadPool * Tp = new myThreadPool(this);QThreadPool::globalInstance()->start(Tp);connect(Tp,&myThreadPool::setNum,this,MainWindow::getNum);//建立信号槽函数}MainWindow::~MainWindow(){delete ui;delete Tp;}void MainWindow :: getNum(int i){ui->label->setText(QString::number(i));//将数字显示在对话框组件中}
头文件#ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QThreadPool>#include <QRunnable>#include <QMainWindow>namespace Ui {class MainWindow;}class myThreadPool :public QObject,public QRunnable//自定义类,公有继承 QObject类和 QRunnable类,【且顺序不能颠倒】{Q_OBJECTpublic:explicit myThreadPool(QWidget *parent = nullptr){}~myThreadPool(){}private:int i;virtual void run()//在run()函数中实现用户自定义功能{while (1){QThread::sleep(1);//间隔一秒emit setNum(i);//发送数字信号函数i++;}}signals:void setNum(int i);//定义一个发送数字信号函数};class MainWindow : public QMainWindow{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = nullptr);~MainWindow();public slots:void getNum(int i);//定义一个接收数字槽函数private:Ui::MainWindow *ui;};#endif // MAINWINDOW_H
线程调用UI组件
一、通过调用线程来实现
class myThreadPhoto : public QThread //自定义一个类,共有继承QThread{Q_OBJECTpublic:explicit myThreadPhoto(QWidget *parent = nullptr){}~myThreadPhoto(){}//重写虚函数virtual void run() //在run函数中执行用户自定义操作{while (1){emit sentPicUpdate(); //每间隔一秒就会发送一个更新图片【自定义信号】信号QThread :: sleep(1);}}signals:void sentPicUpdate(); //建立一个信号,通过发送该信号,建立信号和槽函数,来实现线程调用UI组件};class MainWindow : public QMainWindow //MainWindow类{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_actionstart_triggered();void updatePhoto(); //在MainWindow中创建一个槽函数,用来实现UI组件的调用void on_actionstop_triggered();private:Ui::MainWindow *ui;myThreadPhoto *ph;int dex;};
二、通过线程池来实现调用UI组件
注意:在线程池调用UI组件时,必须要继承QObject,则必须要使用Q_OBJECTclass myThreadPool :public QObject,public QRunnable //myThreadPool继承 QObject类和QRunnable类【顺序不能改变】{Q_OBJECTpublic:explicit myThreadPool(QWidget *parent = nullptr){}~myThreadPool(){}private:int i;virtual void run() //在run函数中实现发送数据{while(1){emit setNum(i);QThread::sleep(1); //每间隔1秒发送一次数据i++;}}signals:void setNum(int i); //在线程池自定义一个信号};class MainWindow : public QMainWindow //在MainWindow 中构建一个槽函数{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = nullptr);~MainWindow();public slots:void getNum(int i); //接收数据槽函数,实现对UI组件的修改,调用private:Ui::MainWindow *ui;};myThreadPool * Tp = new myThreadPool; //在.cpp文件中,创建一个任务QThreadPool::globalInstance()->start(Tp); //线程池接收任务,开启线程池connect(Tp,&myThreadPool::setNum,this,&MainWindow::getNum);//建立信号和槽函数 setNum:在线程池中定义的信号 getNum:在MainWindow 中构建的槽函数