Qt中多线程的使用有三种方式:
1.创建子线程类继承于QThread类,在类中重写虚函数run()的实现,run()函数体则是要执行的任务。然后在主线程中创建子线程对象,然后在需要开启子线程的时候调用start()函数,则内部会自动调用子线程对象的run()函数。
弊端:假设要在一个子线程中处理多个任务,所有的处理逻辑都需要写到run()函数中,这样该函数中的处理逻辑就会变得非常混乱,不太容易维护。
如下:
//方式一
class Task : public QThread
{
public:
Task(QObject *parent):QThread(parent){}
protected:
void run() override //任务函数
{
//要执行的任务
}
};
int main()
{
Task th;
th.start(); //调用start()后会自动启动子线程,并会内部会自动调用run函数。
return 0;
}
2.创建子线程类继承于QObeject类,在类中创建任务函数work(),work()函数体则为要执行的任务,然后在主线程中创建线程对象QThread, 再创建任务对象,将任务对象移动到线程中(调用moveToThread()),调用start()函数启动子线程,但此时子线程中的任务函数并没有执行,必须通过信号槽 的方式将子线程任务函数当作槽函数在合适的时机调用。如下:
//方式二
class Task : public QObject
{
public:
Task(QObject *parent):QObject(parent){}
void work() //任务函数
{
//要执行的任务
}
};
int main()
{
QThread thread;
Task th; //注意:千万不能指定父对象 Task *th =new Task(this);error
th.toMoveThread() //将任务对象移动到子线程中
thread.start(); //调用start()启动子线程,但此时任务函数并没有执行
connect(this,&xinhao,th,&Task::work); //在合适的时机调用work函数,需要通过信号槽的方式使用,需要信号接收对象为子线程类就行,lambada和函数指针都可以
return 0;
}
3.线程池中创建子线程任务,每一个Qt程序都有一个全局的线程池对象,可以通过QThreadPool::globalInstance()获取线程池对象 ,它的返回类型是QThreadpool *,然后创建一个任务类继承于QRunnable,在其构造函数中设置自动释放任务类对象setAutoDelete(),重写任务类的虚函数run(),函数体为要执行的任务,创建任务对象,在合适时机主线程中调用QThreadPool::globalInstance()->start(QRunnbel * runnbel, int priority =0) ,参数是任务对象对象和任务优先级,则会将任务对象扔到线程池中,并自动调用run()函数。如下:
class Task : public QObject,QRunnable
{
public:
Task(QObject *parent):QObject(parent)
{
this->setAutoDelete(true);
}
void run() override //任务函数
{
//要执行的任务
}
};
int main()
{
Task th;
//将任务对象扔进线程池会自动运行run(),线程池会自动管理释放线程对象
QThreadPool::golbalinstance()->start(th);
return 0;
}