下面是关于QT5 Thread线程的具体实现的完整攻略。
1. 基本概念
Qt 中的线程是通过 QThread
类实现的,它提供了多个函数来操作线程,其中比较常用的包括:
start()
:启动线程并执行run()
函数;quit()
:通知线程退出;wait()
:等待线程退出;terminate()
:强制终止线程。
为了自定义线程类,我们需要继承 QThread
类并重写其中的 run()
函数,run()
函数中的代码将在新创建的线程中运行,所以我们可以在 run()
函数中实现自己的线程逻辑。
同时,我们还需要注意线程的安全性问题。多线程环境下,多个线程会访问共享资源,这样容易引发线程安全问题。Qt 也提供了一些线程安全的类和函数,如 QMutex
、QReadWriteLock
、QSemaphore
、QWaitCondition
等。
2. 实现步骤
下面简单介绍一下如何实现自定义的线程类:
2.1 继承 QThread 类
class MyThread : public QThread
{
public:
// MyThread 类构造函数
MyThread(QObject* parent = nullptr);
// 线程运行函数
void run() override;
};
2.2 重写 run 函数
在 run()
函数中编写自己的线程逻辑,这里提供一个简单的示例:
void MyThread::run()
{
for (int i = 0; i < 100; ++i) {
qDebug() << "MyThread:" << i;
sleep(1); // 延时1s
}
}
2.3 创建线程对象
在需要使用的地方创建线程对象:
MyThread thread;
2.4 连接信号和槽
可以将线程对象的 started()
信号连接到自定义槽函数中,以便在线程启动时执行一些初始化工作;同时可以将 finished()
信号连接到自定义槽函数中,以便在线程结束时执行一些清理工作。
// 将 started() 信号连接到槽函数中
connect(&thread, &MyThread::started, this, &MyWidget::on_thread_started);
// 将 finished() 信号连接到槽函数中
connect(&thread, &MyThread::finished, this, &MyWidget::on_thread_finished);
2.5 启动线程
通过调用 start()
函数来启动线程:
thread.start();
2.6 等待线程结束
当线程执行完成后,调用 wait()
函数等待线程退出:
thread.wait();
示例一:线程间通信
下面是一个简单的线程间通信的示例,基本思路是使用信号和槽机制实现。
假设我们需要在主线程中更新一个 QLabel
控件的文本,而这个文本是在子线程中计算的,我们可以将子线程的计算结果通过信号发送到主线程,主线程接收到信号后再更新 QLabel
控件的文本。
定义一个工作线程类:
class WorkerThread : public QThread
{
Q_OBJECT
public:
void run() override
{
// 发送信号
emit resultReady("Hello, world!");
}
signals:
// 声明一个信号,用来通知主线程
void resultReady(const QString& result);
};
在主线程中实例化 WorkerThread
对象,并将其 resultReady()
信号连接到主线程的槽函数中:
// 实例化对象
WorkerThread workerThread;
QString result = "Waiting for result...";
// 将信号连接到槽函数
connect(&workerThread, &WorkerThread::resultReady, this, [&] (const QString& r) {
result = r;
label->setText(result);
});
然后启动线程:
workerThread.start();
注意到这里主线程与工作线程之间在同一个进程中,所以默认情况下,会使用相同的事件循环,这样信号槽机制就能够跨线程工作了。
示例二:线程安全
下面是一个简单的线程安全示例,使用 QMutex
类保护一个共享资源。
假设有两个线程需要对一个共享变量进行读写操作,这样容易引发线程安全问题。为了确保线程安全,我们可以使用 QMutex
来保护这个共享变量。
定义一个共享资源对象:
class SharedResource
{
public:
// 读取共享资源
int readResource() const;
// 写入共享资源
void writeResource(int value);
private:
int m_resource = 0; // 共享资源
mutable QMutex m_mutex; // 互斥锁
};
其中,readResource()
函数使用 const
修饰,表明它不修改任何成员变量,但是需要修改互斥锁的状态,所以需要使用 mutable
关键字。
int SharedResource::readResource() const
{
QMutexLocker locker(&m_mutex); // 上锁
// 读取共享资源
return m_resource;
}
writeResource()
函数则没有使用 const
修饰,表示它会修改成员变量。
void SharedResource::writeResource(int value)
{
QMutexLocker locker(&m_mutex); // 上锁
// 写入共享资源
m_resource = value;
}
总结
以上就是 QT5 Thread 线程的具体实现攻略了,需要注意的是,在使用多线程的过程中,尤其是在访问共享资源的时候,必须要注意线程安全问题,否则会导致程序崩溃或者产生不可预期的结果。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:QT5 Thread线程的具体实现 - Python技术站