Qt线程与并发中创建线程的四种方法

在Qt中实现线程与并发,主要有四种创建线程的方法:

1.继承QThread类并重写run方法,

2.QtConcurrent::run,

3.QThreadPool和QRunnable

4.继承QObject,moveToThread (最常用)

。下面我会详细解释每种方法,并提供相应的示例代码。

方法一:继承QThread并重写run方法

这是最常见的方法。你需要创建一个继承自QThread的类,并在这个类中重写run方法。run方法中的代码将会在新线程中执行。(Qt 4.7之前的线程实现方式)

示例代码

#include <QThread>  
#include <QDebug>  
  
class MyThread : public QThread {  
    Q_OBJECT  
public:  
    void run() override {  
        qDebug() << "Thread ID:" << QThread::currentThreadId();  
        // 线程执行的代码  
    }  
};  
  
int main(int argc, char *argv[]) {  
    QCoreApplication a(argc, argv);  
    MyThread thread;  
    thread.start(); // 启动线程  
    thread.wait(); // 等待线程结束  
    return a.exec();  
}

方法二:使用QtConcurrent::run

QtConcurrent::run是一个更高级别的并发工具,它允许你在不继承QThread的情况下运行函数。这种方法更加简洁,但提供的控制较少。

示例代码

#include <QtConcurrent/QtConcurrent>  
#include <QDebug>  
#include <QFuture>  
  
void myFunction() {  
    qDebug() << "Thread ID (QtConcurrent):" << QThread::currentThreadId();  
    // 线程执行的代码  
}  
  
int main(int argc, char *argv[]) {  
    QCoreApplication a(argc, argv);  
    QFuture<void> future = QtConcurrent::run(myFunction); // 启动线程并执行函数  
    future.waitForFinished(); // 等待线程结束  
    return a.exec();  
}

方法三:使用QThreadPool和QRunnable

QThreadPool和QRunnable是Qt中更高级的线程管理工具,允许你更有效地管理线程资源。你可以创建一个继承自QRunnable的类,并实现run方法。然后,你可以将这个QRunnable对象提交给QThreadPool来执行。

示例代码

#include <QThreadPool>  
#include <QRunnable>  
#include <QDebug>  
  
class MyRunnable : public QRunnable {  
public:  
    void run() override {  
        qDebug() << "Thread ID (QThreadPool):" << QThread::currentThreadId();  
        // 线程执行的代码  
    }  
};  
  
int main(int argc, char *argv[]) {  
    QCoreApplication a(argc, argv);  
    QThreadPool pool; // 创建线程池  
    pool.setMaxThreadCount(5); // 设置线程池的最大线程数  
    MyRunnable *runnable = new MyRunnable(); // 创建QRunnable对象  
    pool.start(runnable); // 将任务添加到线程池并执行  
    pool.waitForDone(); // 等待所有任务完成  
    delete runnable; // 注意:在实际应用中,你可能需要考虑更复杂的内存管理方式。  
    return a.exec();  
}

方法四:继承QObject,moveToThread

使用moveToThread处理线程间数据迁移

moveToThread(QThread *thread)是QObject的一个方法,它允许你将对象及其子对象移动到另一个线程中。这并不意味着对象的数据被“迁移”,而是该对象的事件处理(如槽函数的调用)将在指定的线程中执行。

示例代码

#include <QThread>  
#include <QObject>  
#include <QDebug>  
  
class Worker : public QObject {  
    Q_OBJECT  
public slots:  
    void doWork() {  
        qDebug() << "Working in thread:" << QThread::currentThreadId();  
    }  
};  
  
int main(int argc, char *argv[]) {  
    QCoreApplication app(argc, argv);  
  
    QThread *thread = new QThread();  
    Worker *worker = new Worker();  
  
    // 将worker对象移动到新线程  
    worker->moveToThread(thread);  
  
    // 连接线程的开始信号到worker的槽函数  
    QObject::connect(thread, &QThread::started, worker, &Worker::doWork);  
  
    // 连接线程的结束信号到QObject的deleteLater槽,以确保线程结束时清理资源  
    QObject::connect(thread, &QThread::finished, thread, &QObject::deleteLater);  
    QObject::connect(thread, &QThread::finished, worker, &QObject::deleteLater);  
  
    // 开始线程  
    thread->start();  
  
    return app.exec();  
}

在这个例子中,我们创建了一个Worker类,它继承自QObject并有一个槽函数doWork()。我们实例化了一个QThread对象和一个Worker对象,并使用moveToThread()方法将Worker对象移动到新线程中。然后,我们连接了线程的started信号到Worker的doWork槽,以便线程启动时执行工作。最后,我们连接了线程的finished信号到deleteLater槽以在线程结束时清理资源。

请注意,当你使用moveToThread()时,应确保不要在不同的线程之间直接共享数据,因为这可能导致数据竞争和其他多线程问题。相反,应该使用信号和槽来安全地在线程之间传递数据和消息。

另外,从Qt 5.2开始,建议使用QtConcurrent和QThreadPool来处理并发任务,因为它们提供了更高级别的抽象,使得并发编程更加简单和安全。不过,在某些情况下,使用底层的QThread和moveToThread()仍然是必要的,特别是当你需要更精细地控制线程的行为时。

线程间的同步和互斥

Qt提供了多种同步机制,如QMutex、QSemaphore、QWaitCondition等,以实现线程间的同步和互斥。例如,QMutex可以保护共享资源,确保同一时间只有一个线程可以访问。QWaitCondition可以与QMutex一起使用,以实现更复杂的线程同步需求。

线程的异常处理

在Qt中,线程的异常处理通常通过信号和槽机制来实现。你可以在线程的run方法中捕获异常,并通过发射信号来通知主线程或其他线程进行处理。此外,你也可以使用QCoreApplication::aboutToQuit()信号来安全地结束线程。

总的来说,Qt提供了多种灵活且强大的线程和并发工具,可以根据具体需求选择最适合的方法。在选择创建线程的方法时,需要考虑线程的生命周期管理、资源共享和同步、异常处理等因素。

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值