QT多线程实现方式

QT多线程

1. 重写run()函数

使用线程步骤

  1. 包含相关的头文件:
#include <QThread>
  1. 创建一个继承自QThread的子类:

创建一个新的类,继承自QThread,并重写其run()函数。
在run()函数中编写多线程需要执行的代码。

class MyThread : public QThread
{
    Q_OBJECT

public:
    void run() override
    {
        // 在这里编写多线程需要执行的代码
    }
};
  1. 创建并启动线程:

在界面或其他需要的地方,创建一个MyThread对象,并调用其start()函数来启动线程。

MyThread myThread;
myThread.start();

  1. 处理线程完成信号(可选):

如果需要在主线程中处理线程完成的信号,可以连接线程的finished()信号到相应的槽函数。

connect(&myThread, &MyThread::finished, this, &MyClass::onThreadFinished);

  1. 退出线程:

退出线程,停止底层的事件循环

//退出线程的工作函数
void QThread::exit(int returnCode = 0);
//调用线程退出函数之后,线程不会马上退出因为当前任务有可能还没有完成

void QThread::wait();
//等待任务完成,然后退出线程,一般情况会在exit()后面调用这个函数

常用函数

公有函数:

函数功能
bool isFinished()线程是否结束
bool isRunning()线程是正在运行
Priority priority()返回线程的优先级
void setPriority(Priority priority)设置线程的优先级
void exit(int returnCode = 0)退出线程的事件循环,退出码为returnCode,0表示成功退出,否则表示有误
bool wait(unsigned long time)阻止线程执行,直到线程结束(从run()函数返回),或等待时间超过time毫秒

信号

函数功能
void finished()在线程就要结束时发射此信号
void started()在线程开始执行,run()函数被调用之前发射此信号

代码示例:

#include <QThread>
#include <QDebug>

class MyThread : public QThread
{
public:
    void run() override
    {
        qDebug() << "Thread started";

        // 线程执行的逻辑代码
        for (int i = 0; i < 5; ++i) {
            qDebug() << "Thread running" << i;
            sleep(1); // 线程暂停1秒
        }

        qDebug() << "Thread finished";
    }
}; 

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    MyThread thread;
    thread.start(); // 启动线程

    // 在主线程中进行其他操作

    thread.wait(); // 等待线程执行完毕

    return app.exec();
}


2. 使用 moveToThread()

方法和步骤:

  1. 在主线程中创建一个新的线程:通常使用 QThread 或其子类来创建一个新的线程对象。
  2. 创建新的任务类继承QObject类,创建成员函数处理相应逻辑
  3. 将要移动到新线程的对象的指针传递给 moveToThread() 函数,以便将该对象从当前线程中分离出来并移动到新线程中运行。
  4. 在新线程中执行对象的工作:在新线程中调用对象的 start() 函数,启动新线程并开始执行对象的工作。
// 1.创建任务类
MyObject *obj = new MyObject();

// 2.创建一个新的线程
QThread *thread = new QThread();

// 3.将任务类对象移动到新线程中运行
obj->moveToThread(thread);

// 连接线程的 started() 信号和对象的 doWork() 槽函数
connect(thread, &QThread::started, obj, &MyObject::doWork);

// 连接对象的 finished() 信号和线程的 quit() 和 deleteLater() 槽函数
connect(obj, &MyObject::finished, thread, &QThread::quit);//终止线程的事件循环,使线程退出
connect(obj, &MyObject::finished, obj, &MyObject::deleteLater);//在下一个事件循环中删除对象,确保对象在被使用完毕后被正确释放。

// 连接线程的 finished() 信号和线程的 deleteLater() 槽函数
connect(thread, &QThread::finished, thread, &QThread::deleteLater);

// 启动新线程并等待它结束
thread->start();
thread->wait();

//第一种方式为传递父对象
//第二种方式为手动释放:
connect(this,&MainWindow::destroyed(),this,[=]()
{
	thread->quit();
	thread->wait();
	thread->deleteLater();
	
	
});

3. 线程池

线程池是一种管理多个线程的机制,可以用于处理并发任务,提高程序性能和响应速度。
线程池可以预先创建一定数量的线程,并维护一个任务队列,当有任务到来时,线程池会从空闲线程中获取一个线程来执行任务,执行完毕后将该线程释放回线程池,等待下一个任务的到来。

常用函数

- globalInstance();   //获取全局线程池实例。
- setMaxThreadCount(int maxThreadCount);   //设置线程池中线程的最大数量。
- start(QRunnable *runnable);   //将一个任务对象添加到线程池中并开始执行任务。
- activeThreadCount();   //获取当前活动的线程数量。
- expiryTimeout();   //获取线程池的过期超时时间。
- setExpiryTimeout(int expiryTimeout);   //设置线程池的过期超时时间。
- waitForDone(int msecs);   //等待线程池中所有任务执行完毕,最多等待指定的时间。
- clear();   //清除线程池中所有任务,并等待任务的执行完成。
- tryStart(QRunnable *runnable);   //尝试将一个任务对象添加到线程池中开始执行,如果没有空闲线程,则不执行任务。
- reserveThread();   //预留一个线程,即使没有任务,该线程也会一直存在。
- releaseThread();   //释放一个预留线程。

代码示例:

Qt 提供了 QThreadPool 类来实现线程池,QThreadPool管理和回收各个QThread对象

// 创建线程池对象
QThreadPool *pool = QThreadPool::globalInstance();

// 设置线程池中线程的最大数量
pool->setMaxThreadCount(4);

// 创建任务对象
MyTask *task1 = new MyTask();
MyTask *task2 = new MyTask();
MyTask *task3 = new MyTask();

// 将任务对象添加到线程池中
pool->start(task1);
pool->start(task2);
pool->start(task3);
//QThreadPool::globalInstance()->start(task);
//在程序中显式地使用了 new 运算符创建了一个线程池对象,需要在不再需要该对象时手动调用 delete 运算符来释放它。
//对于全局线程池对象,不需要手动释放,Qt会处理它的生命周期。

在使用 QThreadPool 时,还需要实现自定义的任务类,继承自 QRunnable,并重写 run() 方法,在其中编写具体的任务逻辑。
通过 start() 方法将任务对象添加到线程池中后,线程池会自动分配线程来执行任务。

//想要在任务对象里面使用QT提供的信号槽机制,需要继承QObject
class MyTask : public Qobject, public QRunnable
{
		Q_OBJECT;
public:
    explicit Mytask(QObject *parent = nullptr)
    {
        //任务执行完毕,该对象自动销毁
        setAutoDelete(true);
    }     
	
    void run() override
    {
        // 执行任务的具体逻辑
    }
};

4. Qtconcurrent

QtConcurrent 是 Qt 提供的一个模块,提供了一种更高级的并发编程框,用于简化多线程编程和并发执行任务。
它基于函数式编程的理念,允许你以一种更加高级和直观的方式在多个线程中执行函数或者 Lambda 表达式。

主要功能:

QtConcurrent::run()

QtConcurrent::run() 函数是最简单的 QtConcurrent 使用方式,它可以在新线程中执行一个函数或者 Lambda 表达式。

void myFunction() {
    // 在这里编写需要在新线程中执行的代码逻辑
}

// 在新线程中执行函数
QtConcurrent::run(myFunction);

QtConcurrent::map()

QtConcurrent::map() 函数可以对一个序列中的每个元素并行地执行一个函数,并返回结果序列。
这个函数类似于标准库中的 std::transform,但是可以并行执行。

QList<int> inputList = {1, 2, 3, 4, 5};

// 对序列中的每个元素执行函数,返回结果序列
QList<int> outputList = QtConcurrent::map(inputList, [](int value) {
    return value * 2;
});

QtConcurrent::filter()

QtConcurrent::filter() 函数可以对一个序列中的元素并行地执行一个谓词函数,并返回满足条件的元素组成的序列。

QList<int> inputList = {1, 2, 3, 4, 5};

// 过滤序列中的元素,返回满足条件的元素组成的序列
QList<int> filteredList = QtConcurrent::filter(inputList, [](int value) {
    return value % 2 == 0;
});

QtConcurrent::mapped() 和 QtConcurrent::filtered()

QtConcurrent::mapped() 和 QtConcurrent::filtered() 是对 map() 和 filter() 的延迟版本,它们返回一个 QFuture 对象,允许你延迟执行并发操作。

QList<int> inputList = {1, 2, 3, 4, 5};

// 延迟执行 map 操作
QFuture<int> future = QtConcurrent::mapped(inputList, [](int value) {
    return value * 2;
});

// 获取结果
QList<int> outputList = future.results();
  • 60
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt是一个跨平台的应用程序框架,提供了丰富的多线程编程支持。Qt多线程编程主要依靠QThread类和信号槽机制来实现QThread类封装了线程的基本操作,使得我们可以通过继承这个类来实现自己的线程。通过重写QThread类中的run()方法,我们可以在这个方法中实现具体的线程操作。 例如,下面是一个简单的QThread子类的定义: ```c++ class MyThread : public QThread { Q_OBJECT public: explicit MyThread(QObject *parent = nullptr); protected: void run() override; signals: void resultReady(int result); }; ``` 在这个例子中,我们重写了run()方法来实现线程的具体操作。在这个方法中,我们可以调用其他Qt类或者自己实现的函数来完成多线程的任务。另外,我们还定义了一个resultReady信号,用于在线程执行完毕后向主线程发送消息。 接下来,我们可以在主线程中创建一个MyThread对象,并连接它的resultReady信号到一个槽函数中,以便在线程执行完毕后处理结果。例如: ```c++ MyThread *thread = new MyThread(this); connect(thread, &MyThread::resultReady, this, &MyClass::handleResult); thread->start(); ``` 在这个例子中,我们创建一个MyThread对象并启动它。在线程执行完毕后,它会发送resultReady信号,我们将这个信号连接到handleResult槽函数中来处理结果。 除了QThread类外,Qt还提供了许多其他的多线程编程工具,如QThreadPool类、QMutex类、QWaitCondition类等,可以帮助我们更方便地实现多线程编程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值