线程基础
一、类QThread
创建线程的,一个线程有一个类,该类继承QThread即可,重写run则是他的行为,实例化后直接.start()开始线程;
//继承QThread的Mythread中重写run()
void MyThread::run()
{
for(int i=1;i<=5;i++)
{
qDebug()<<i;
sleep(1);
}
}
二、类QSemaphore
- 信号量,实现信号的同步,即线程执行顺序
- 信号量的类需要声明为单例模式,即仅在第一次调用时生成静态指针
//信号量管理类的头文件
#ifndef SEMMANAGER_H
#define SEMMANAGER_H
#include <QSemaphore>
class SemManager
{
public:
//信号量AB
QSemaphore A;
QSemaphore B;
//必须设置成单例模式
static SemManager* getInstance();
private:
static SemManager* instance; //静态数
SemManager();
};
#endif // SEMMANAGER_H
//信号量管理类的实现文件
#include "semmanager.h"
SemManager* SemManager::instance=0;
SemManager::SemManager()
:A(1),B(0)
{
//注意互斥量的初始话
}
SemManager* SemManager::getInstance()
{
//创建一次后不再为0,实现了单例模式
if(instance == 0)
{
instance= new SemManager;
}
//每次调用都是得到该静态变量指针
return instance;
}
- 真正使用时: 两线程都需要在开始后调用SemManager::getInstance()实例化信号量管理类,但其实是同一个,再在行为中对信号量进行操作
void MyThread1::run()
{
SemManager *sm=SemManager::getInstance();
for(int i=1;i<=5;i++)
{
sm->B.acquire(); //默认是0,所以启动时是不可以执行的
qDebug()<<i*10;
sleep(1);
sm->A.release();
}
}
- 类QSemaphore的函数接口
QSemaphore::QSemaphore(int n=0); //构造函数,i信号量数
int QSemaphore::avilable(); //获取信号量的剩余数
void QSemaphore::release(int n=1); //添加信号量
void QSemaphore::acquire(int n=1); //减少信号量
三、类QMutex
- 类QMutex用于保护一段代码在同一时刻只有一个线程可以执行。对QMutex对象可以进行上锁和解锁的操作。当某线程对QMutex对象上锁后,其他线程在对QMutex对象上锁时,线程会阻塞,直到QMutexi对象被解锁
- 可实现对全局资源的互斥使用
- QMutex的函数接口
//需要在线程对象中添加
QMutex mutex; //锁属性
//在线程的run中
mutex.lock(); //头加入
mutex.unlock();//尾加入
//上面是同个线程类实例出不同对象的操作,但事实上是需要是对资源进行的操作
线程高级
一、主线程来负责刷新界面等
- 当QT程序启动时会调用QApplication:exec()启动事件循环,该线程称之为主线程。
- 主线程的主要作用是处理各种界面的事件和槽函数。而当槽函数耗时过长时会导致界面出现卡顿的现象,影响用户体验。
- 顾可以使用线程来执行槽函数
- 可以使用以下QObjecti的成员函数来将某个对象的槽函数交给线程执行:void QObject::moveToThread(QThread *tragetThread);
- 注意:任何继承自QObject的对象都可以使用该成员函数,但是使用该函数时必须确保该对象在构造时没有指定父对象。
- 代码的意思:一个窗口,点击时候触发槽函数,槽函数是每一秒发一个信号(该信号的槽函数是显示数字),发五次。
- 使用QThread自带的事件循环,将槽函数交由线程处理