泉州市建设工程交易网站,wordpress 底部音乐播放器插件,广州网站快速排名优化,网页设计欣赏app一、线程QThread
QThread 类提供不依赖平台的管理线程的方法#xff0c;如果要设计多线程程序#xff0c;一般是从 QThread继承定义一个线程类#xff0c;在自定义线程类里进行任务处理。qt拥有一个GUI线程,该线程阻塞式监控窗体,来自任何用户的操作都会被gui捕获到,并处理…一、线程QThread
QThread 类提供不依赖平台的管理线程的方法如果要设计多线程程序一般是从 QThread继承定义一个线程类在自定义线程类里进行任务处理。qt拥有一个GUI线程,该线程阻塞式监控窗体,来自任何用户的操作都会被gui捕获到,并处理;如果有耗时的任务,不推荐在GUI中处理.怎么办?? 创建线程,交给线程去耗时!
1.QThread类简要说明
一个QThread类的对象管理一个线程。该线程包括
执行函数体这是线程执行的主要代码部分。函数体中有一个死循环用于保持线程的持续运行直到条件满足。线程私有空间每个线程都有自己的独立数据和堆栈空间。
QThread 提供了完整的线程功能并且内置了一个虚函数 run() 用于处理线程任务。我们可以通过重写 run() 方法来定义线程的具体行为。编写线程的具体方法为继承QThread并重写run()函数。最好是直接定义一个线程类实际上也这样做。GUI线程和控件访问只有主GUI线程可以访问和操作窗体上的控件。如果其他线程尝试直接访问这些控件会导致程序崩溃。为了在线程中更新UI可以使用信号和槽机制。
class MyThread : public QThread {Q_OBJECT
signals:void updateUI(int value);public:void run() override {for (int i 0; i 10; i) {emit updateUI(i); // 发出信号更新UIQThread::sleep(1);}}
};// 在主窗口类中连接信号和槽
connect(ptMyThread, MyThread::updateUI, this, MainWindow::updateUIFunction);
线程的启动和停止使用start()和stop()函数即可。这也是可以捕获的信号可以用来连接槽函数不过要加上ed。出现了此类错误error: undefined reference to vtable for myThread那么就将该错误发生的头文件和函数体文件移除该工程然后再添加进来。代码举例
2.线程间通信
1.通过共享资源的方式可以进行线程间通信。
结构体通信 值得注意的就是使用之前要加锁使用之后要解锁
QMutex buflock;//其实就是互斥信号量。
buflock.lock();
buflock.unlock();结构体要在使用该结构体的线程中声明定义在外面方便其他线程使用或声明当然互斥锁也要有哈。 一般通过构造函数传入或写出数据。 在重写run()函数里有while循环或者是死循环具体情况而定 当然也要有休眠函数给其他线程一点时间执行嘛。 代码举例
//rethread.h
#ifndef RETHREAD_H
#define RETHREAD_H
#includeQThread
#includeQMutexstruct msg_struct{int temp;int shidu;char des[128];
};class thread_write:public QThread{
public:thread_write();thread_write(struct msg_struct *pmsg,QMutex *pMutex);//写~thread_write();void run() override;//写。重写
private:struct msg_struct *pShareMsg;QMutex *pMutex;
};class thread_read:public QThread{
public:thread_read(struct msg_struct *pmsg,QMutex *pMutex);//写thread_read();~thread_read();void run() override;//重写
private:struct msg_struct *pShareMsg;QMutex *pMutex;};#endif // RETHREAD_H//rethread.cpp
#include rethread.h
#includeQDebugthread_write::thread_write()
{}thread_write::thread_write(msg_struct *pmsg, QMutex *pMutex)
{pShareMsg pmsg;this-pMutexpMutex;
}thread_write::~thread_write()
{}void thread_write::run()
{char ch A;while(1){pMutex-lock();for(int i 0;i127;i){pShareMsg-des[i]ch;if(i%200){QThread::sleep(1);}}pMutex-unlock();QThread::msleep(10);ch;}
}thread_read::thread_read(msg_struct *pmsg, QMutex *pMutex)
{pShareMsg pmsg;this-pMutex pMutex;}thread_read::thread_read()
{}thread_read::~thread_read()
{}void thread_read::run()
{QThread::sleep(1);while(1){pMutex-lock();qDebug()thread read__func__ pShareMsg-des;pMutex-unlock();QThread::sleep(5);}
}//widget.h
#ifndef WIDGET_H
#define WIDGET_H
#includerethread.h
#include QWidgetQT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();private:Ui::Widget *ui;struct msg_struct *pShareMsg;QMutex *pMutex;thread_read *pThreadRead;thread_write *pThreadWrite;
};
#endif // WIDGET_H//widget.cpp
#include widget.h
#include ui_widget.hWidget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);pShareMsg new struct msg_struct;pMutex new QMutex;pThreadRead new thread_read(pShareMsg,pMutex);pThreadWrite new thread_write(pShareMsg,pMutex);pThreadWrite-start();pThreadRead-start();
}Widget::~Widget()
{delete ui;
} 信号和槽
在一个线程中定义一个信号然后将其连接到另一个线程中的槽函数通过信号的触发来调用槽函数。这是Qt中最常用的线程间通信方法。这之中有一个线程铁定是GUI线程。才可以使用信号和槽例如 输出为 值得注意的是不要在GUI程序中加入sleep睡眠之类的代码容易造成程序崩溃。
3.线程间同步
线程同步是指在多线程环境中协调线程之间的执行顺序和数据共享确保线程以预期的方式访问共享资源。同步的主要目的是避免竞争条件race conditions和数据不一致性。
1.基于互斥量的线程同步QMutex
互斥量可以保证在任意时刻只有一个线程可以访问共享资源从而避免竞争条件和数据不一致性。定义一把互斥锁
//widget.h
QMutex *pMutex;
//widget.cpp
pMutex new QMutex;上锁如果互斥量已经被其他线程锁定当前线程将被阻塞直到互斥量可用。
pMutex.lock();解锁访问共享资源后线程需要释放互斥量的锁以便其他线程可以访问该资源。
pMutex.unlock();尝试上锁函数tryLock()尝试锁定一个互斥量如果成功锁定就返回true如果其他线程已经锁定了这个互斥量就返回false不等待。有参数则等待。
pMutex.try_Lock();//括号内可以有参数以毫秒为单位表示最多等待多少毫秒2. 基于读写锁的线程同步QReadWriteLock
基于读写锁Read-Write Lock的线程同步是一种高效的同步机制适用于读多写少的场景。与互斥锁不同读写锁允许多个线程同时读取共享资源但在写入资源时只允许一个线程进行写操作这样可以提高程序的并发性能。
定义一把读写锁
//widget.h
QReadWriteLock *pRWLock;
//Widget.cpp
pRWLock new QReadWriteLock;pRWLock.lockForRead();//以只读方式锁定资源如果有其他线程以写入方式锁定资源这个函数会被阻塞pRWLock.lockForWrite();//以写入方式锁定资源如果其他线程以读或写方式锁定资源这个函数会被阻塞pRWLock.unlock();//解锁它们可以在前面加上try如tryLockForRead();表示尝试以读的方式锁上资源括号内的参数可以表示尝试多少毫秒
3. 基于条件等待的线程同步QWaitCondition
QWaitCondition 提供了一种改进的线程同步方法QWaitCondition 通过与 QMutex 或QReadWriteLock 结合使用可以使一个线程在满足一定条件时通知其他多个线程使其他多个线程及时进行响应这样比只使用互斥量或读写锁效率要高一些。定义 QMutex mutex;
QReadWriteLock readWriteLock;
QWaitCondition condition;bool wait(QMutex *lockedMutex, unsigned long time ULONG_MAX)释放lockMutex这个互斥信号量。线程进入休眠等待被唤醒默认无限等待。若被唤醒则返回true若超时则返回false。bool wait(QReadWriteLock *lockedReadWriteLock, unsigned long time ULONG_MAX)释放lockedReadWriteLock这个读写锁并让线程进入等待状态直到被唤醒或者超时。默认情况下无限期等待。若被唤醒则返回true若超时则返回false。void wakeAll()唤醒所有处于等待状态的线程。唤醒顺序不确定由操作系统的调度策略决定。void wakeOne()唤醒一个处于等待状态的线程。具体唤醒哪个线程不确定由操作系统的调度策略决定。
4. 基于信号量的线程同步
信号量QSemaphore是用于控制多个线程对共享资源的访问的同步原语。它是一种计数器允许你在特定时间允许多个线程同时访问某个资源。信号量可以用来限制访问的线程数。
使用方法
方法名描述参数返回值构造函数QSemaphore(int initialCount 1, int maxCount 1)创建一个信号量初始计数和最大计数。initialCount初始计数值maxCount最大计数值无基本方法acquire(int num 1)获取 num 个资源若资源不足线程阻塞。num需要获取的资源数量无release(int num 1)释放 num 个资源增加信号量的计数器。num需要释放的资源数量无带超时的方法acquire(int num, unsigned long timeout ULONG_MAX)获取 num 个资源直到超时。num需要获取的资源数量timeout超时时间毫秒bool成功获取资源返回 true超时返回 false检查方法tryAcquire(int num 1)尝试获取 num 个资源若资源不足则立即返回。num需要获取的资源数量bool成功获取资源返回 true否则返回 falseavailable() const返回可用资源的数量。int可用资源数量其他方法setCount(int count)设置信号量的计数器值。count新的计数值无maximumCount() const返回信号量的最大值。int最大值currentCount() const返回当前信号量的计数值。int当前计数值
代码示例
#include QCoreApplication // 引入Qt核心应用程序模块
#include QThread // 引入Qt线程模块
#include QSemaphore // 引入Qt信号量模块
#include QDebug // 引入Qt调试输出模块// 创建一个信号量初始计数为3表示最多同时允许3个线程访问资源
QSemaphore semaphore(3);class Worker : public QThread {
public:void run() override { // 重写QThread的run()方法定义线程执行的代码// 尝试在1000毫秒内获取一个资源if (semaphore.tryAcquire(1, 1000)) { // 尝试获取一个资源如果在超时内未能获取则返回falseqDebug() Thread QThread::currentThreadId() acquired a resource.; // 打印线程获取资源的消息QThread::sleep(2); // 模拟工作线程休眠2秒qDebug() Thread QThread::currentThreadId() finished working.; // 打印线程完成工作的消息semaphore.release(); // 释放一个资源使其他等待的线程可以获取到资源} else {qDebug() Thread QThread::currentThreadId() could not acquire a resource within timeout.; // 打印超时未获取资源的消息}// 显示信号量的状态qDebug() Current available resources: semaphore.available(); // 打印当前可用资源的数量semaphore.setCount(5); // 修改信号量的计数器值为5增加可用资源qDebug() Max count: semaphore.maximumCount(); // 打印信号量的最大计数值qDebug() Current count: semaphore.currentCount(); // 打印当前信号量的计数值}
};int main(int argc, char *argv[]) {QCoreApplication a(argc, argv); // 创建Qt应用程序实例// 创建多个Worker线程实例Worker worker1, worker2, worker3, worker4, worker5;// 启动线程worker1.start();worker2.start();worker3.start();worker4.start();worker5.start();// 等待所有线程完成worker1.wait();worker2.wait();worker3.wait();worker4.wait();worker5.wait();return a.exec(); // 进入Qt事件循环
}
QT睡眠程序
用于让当前线程休眠或延迟执行
QThread::sleep(int sec)//个方法使当前线程休眠指定的秒数。QThread::msleep(int msec);//这个方法使当前线程休眠指定的毫秒数。QThread::usleep(int usec);//这个方法使当前线程休眠指定的微秒数。