lesson15-QT多线程

简介: 一、什么是线程 1、线程 进程:一个正在执行的程序,它是资源分配的最小单位 线程:程序执行的最小单位 进程出现了很多弊端,一是由于进程是资源拥有者,创建、撤消与切换存在较大的时空开销,因此需要引入轻型进程;二是由于对称多处理机(SMP)出现,可以满足多个运行单位,而多个进程并行开销过大。
一、什么是线程
1、线程
进程:一个正在执行的程序,它是资源分配的最小单位
线程:程序执行的最小单位

进程出现了很多弊端,一是由于进程是资源拥有者,创建、撤消与切换存在较大的时空开销,因此需要引入轻型进程;二是由于对称多处理机(SMP)出现,可以满足多个运行单位,而多个进程并行开销过大。

2、线程的术语
并发是指在同一时刻,只能有一条指令执行,但多个进程指令被快速轮换执行,使得在宏观上具有多个进程同时执行的效果。 
看起来同时发生

并行是指在同一时刻,有多条指令在多个处理器上同时执行。
真正的同时发生

同步:彼此有依赖关系的调用不应该“同时发生”,而同步就是要阻止那些“同时发生”的事情
异步的概念和同步相对,任何两个彼此独立的操作是异步的,它表明事情独立的发生

3、线程的优势
1)、在多处理器中开发程序的并行性
2)、在等待慢速IO操作时,程序可以执行其他操作,提高并发性
3)、模块化的编程,能更清晰的表达程序中独立事件的关系,结构清晰
4)、占用较少的系统资源

多线程不一定要多处理器
GUI程序中经常会使用多线程技术,一个线程用来响应界面,而其他线程就可以在后台处理冗长的操作
Qt的元对象系统支持不同线程中的对象使用信号和槽机制通信




二、QT多线程
Qt中使用多线程是非常简单的,只要子类话QThread就可以了,在QThread中有一个protected类型的run函数,重写run函数就可以实现多线程。
1、QT线程
Qt中使用多线程是非常简单的,只要子类化QThread,然后重写run函数就可以实现多线程

class MyThread:public Thread
{
public:
 MyThread();
protected:
 void run();
private:
 volatile boolean stopped;
}

run函数是通过线程的start方法启动的,线程还有isRunning方法来判断是否在运行,terminate方法结束线程
 

2、线程同步之信号量
信号量使线程不需要忙碌的等待,是对mutex的一种扩展。使用信号量可以保证两个关键代码不会并发。在进入一段关键代码时,线程必须获取信号量,退出时必须释放。信号量可以同时由多个线程访问。

Qt的信号量QSemaphore类:
acquire()用来获取资源,free()用来释放资源

生产者和消费者的例子,生产者生产的时候需要确保有足够的空间,消费者消费的时候要确保空间里有资源
QSemaphore freeByte(100) 生产有有100个空间
QSemaphore useByte(0)消费者没有资源
producer
{
  freeByte.acquire()
  byte = n
  useByte.release()
}
consumer
{
  useByte.acquire()
  printf byte
  freeByte.release()
}


3、线程同步之条件变量
QWaitCondition允许线程在一定条件下唤醒其他的线程,这样也可以是线程不必忙碌的等待,条件变量要配合互斥量来使用

QMutex mutex; QWaitCondition condition;
condition.wait(&mutex)
condition.wakeAll()
wait函数将互斥量解锁,并在此等待,此函数返回之前会将互斥量重新枷锁。
wakeAll函数会将所有等待该互斥量的线程唤醒
 

4、线程优先级
实际任务可能会让某个线程先运行,那么就需要设置线程优先级。
setPriority函数可以设置线程的优先级,或者在线程启动的时候在start函数传入线程的优先级


三、实例
1、多线程

点击(此处)折叠或打开

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include QThread>

class MyThread : public QThread
{
Q_OBJECT
public:
    MyThread();
    void stop();
    volatile bool stopped;
protected:
    void run();
};
#endif

点击(此处)折叠或打开

#include "myThread.h"
#include QtDebug>

MyThread::MyThread()
{
    stopped = false;
}

void MyThread::run()
{
    int i=0;
    while(!stopped)
    {
        qDebug()"thread id:"QThread::currentThreadId()":"i;
        i++;
        sleep(2);
    }
    stopped = false;
}

void MyThread::stop()
{
    stopped = true;
}

2、信号量

点击(此处)折叠或打开

#ifndef PRODUCER_H
#define PRODUCER_H

#include QThread>

class Producer : public QThread
{
Q_OBJECT
public:
    Producer();
protected:
    void run();
};

#endif

点击(此处)折叠或打开

#ifndef CONSUMER_H
#define CONSUMER_H

#include QThread>

class Consumer : public QThread
{
Q_OBJECT
public:
    Consumer();
protected:
    void run();
};

#endif

点击(此处)折叠或打开

#include "producer.h"
#include "consumer.h"
#include QDebug>
#include QSemaphore>

#define SIZE 50
QSemaphore freeByte(SIZE);
QSemaphore useByte(0);

Producer::Producer()
{

}
void Producer::run()
{
    for(int i=0; iSIZE; i++)
    {
        freeByte.acquire();
        qDebug()"produer:"i;
        useByte.release();
        sleep(1);
    }
}
Consumer::Consumer()
{

}
void Consumer::run()
{
    for(int i=0; iSIZE; i++)
    {
        useByte.acquire();
        qDebug()"consumer:"i;
        freeByte.release();
        sleep(2);
    }
}


3、条件变量

点击(此处)折叠或打开

#ifndef THREAD_H
#define THREAD_H

#includeQThread>

class Producer : public QThread
{
Q_OBJECT
public:
    Producer();
protected:
    void run();
};

class Consumer : public QThread
{
Q_OBJECT
public:
    Consumer();
protected:
    void run();
};

#endif

点击(此处)折叠或打开

#include "thread.h"
#include QDebug>
#include QMutex>
#include QWaitCondition>

QMutex mutex;
QWaitCondition empty, full;
int num=0;
int buffer[50];
int useByte=0;


Producer::Producer()
{

}
void Producer::run()
{
    for(int i=0; i50; i++)
    {
        mutex.lock();
        if(useByte==50)
            empty.wait(&mutex);
        num++;
        buffer[i] = num;
        qDebug()"producer:"num;
        useByte++;
        full.wakeAll();
        mutex.unlock();
        sleep(1);
    }
}
Consumer::Consumer()
{

}
void Consumer::run()
{
    for(int i=0; i50; i++)
    {
        mutex.lock();
        if(useByte==0)
            full.wait(&mutex);
        qDebug()"consumer"buffer[i];
        useByte--;
        empty.wakeAll();
        mutex.unlock();
        sleep(2);
    }
}



相关文章
|
7月前
|
算法 Unix 调度
【Qt 线程】深入探究QThread线程优先级:原理、应用与最佳实践
【Qt 线程】深入探究QThread线程优先级:原理、应用与最佳实践
549 0
|
7月前
|
安全 Java
Qt经典面试题:Qt开启线程的几种方式
Qt经典面试题:Qt开启线程的几种方式
126 0
|
7月前
|
算法 Unix Linux
Linux与Qt线程优先级的对应关系:一次全面解析
Linux与Qt线程优先级的对应关系:一次全面解析
92 0
|
7月前
|
安全 数据处理 C++
【Qt 底层之事件驱动系统】深入理解 Qt 事件机制:主事件循环与工作线程的交互探究,包括 QML 的视角
【Qt 底层之事件驱动系统】深入理解 Qt 事件机制:主事件循环与工作线程的交互探究,包括 QML 的视角
1491 3
|
7月前
|
存储 安全 Java
Qt线程池+生产者消费者模型
Qt线程池+生产者消费者模型
299 5
|
3月前
|
网络协议 安全
QT多线程
本文详细介绍了在Qt中如何正确使用QThread以及信号槽跨线程的使用方式,包括线程的正确退出方法和QObject在不同线程中创建子对象时可能遇到的问题。同时,文章还提供了相关博客和资料的链接,用于进一步学习和参考。
|
3月前
|
数据库 数据库管理
qt对sqlite数据库多线程的操作
本文总结了在Qt中进行SQLite数据库多线程操作时应注意的四个关键问题,包括数据库驱动加载、加锁、数据库的打开与关闭,以及QsqlQuery变量的使用。
209 1
|
3月前
自己动手写QT多线程demo
本文是作者关于如何编写Qt多线程demo的教程,介绍了如何实现多线程功能,包括可暂停和继续的功能。文章提供了部分示例代码,展示了如何创建线程类、启动和管理线程,以及线程间的通信。同时,还提供了相关参考资料和免费下载链接。
|
5月前
|
调度
【浅入浅出】Qt多线程机制解析:提升程序响应性与并发处理能力
在学习QT线程的时候我们首先要知道的是QT的主线程,也叫GUI线程,意如其名,也就是我们程序的最主要的一个线程,主要负责初始化界面并监听事件循环,并根据事件处理做出界面上的反馈。但是当我们只限于在一个主线程上书写逻辑时碰到了需要一直等待的事件该怎么办?它的加载必定会带着主界面的卡顿,这时候我们就要去使用多线程。
168 6
|
7月前
|
Java API C++
【C++ 与Qt 线程】C++ std::thread 与Qt qthread多线程混合编程
【C++ 与Qt 线程】C++ std::thread 与Qt qthread多线程混合编程
268 1