背景
项目中用到多线程,对线程的执行顺序有要求:
A.一个线程先收数据
B.一个线程处理数据
C.一个线程再将处理后的数据发送出去

要求三个线程按照ABC的顺序循环执行。

思路
子类化多线程方法
重写子类的run函数,在run函数内用while(1)来常驻线程,循环体内通过检查全局变量来判断是否到自己执行,不是自己线程则跳过,是自己线程执行完后改变全局标志位。通过全局标志位来控制线程的执行顺序。所以需要一个全局变量来标记当前应当执行的线程,同时用一个互斥量来保护该全局变量。
movetoThread多线程方法
为每个线程设计相应的方法类,将生成的方法类对象移入到对应的线程内,方法类的方法必须通过信号和槽的方式来触发。
本文采用第二种思路来实现线程的顺序执行

QWaitConditon简介
线程如何睡眠?

调用QWaitCondition的wait函数将使得调用它的线程进入睡眠状态

线程如何醒来?

在另外的线程中调用QWaitConditon的wakeOne或者wakeAll方法将唤醒等待它的线程

实现过程
先定义全局变量
QWaitCondition condition_input; //数据收线程的条件变量,控制线程睡眠和唤醒
QWaitCondition condition_process;//数据处理线程的条件变量,控制线程睡眠和唤醒
QWaitCondition condition_output;//数据发线程的条件变量,控制线程睡眠和唤醒

//保护条件变量,防止多线程同时访问条件变量
QMutex mutex_input;
QMutex mutex_process;
QMutex mutex_output;
1
2
3
4
5
6
7
8
2.实现接收数据的方法的槽函数

void input::work()
{
while(1)//使得线程常驻
{
qDebug()<<"input1";
mutex_process.lock();
condition_process.wakeOne();//唤醒下一次的数据处理线程
mutex_process.unlock();
mutex_input.lock();
condition_input.wait(&mutex_input);//睡眠当前的收线程
mutex_input.unlock();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
3.实现处理数据的方法的槽函数

void process::work()
{
while (1)
{
qDebug()<<"process2";
mutex_output.lock();
condition_output.wakeOne();//唤醒下一次的发线程
mutex_output.unlock();
mutex_process.lock();
condition_process.wait(&mutex_process);//睡眠当前处理线程
mutex_process.unlock();
}
}

void process::threadSleep()
{
qDebug()<<QThread::currentThreadId();
mutex_process.lock();
condition_process.wait(&mutex_process);//睡眠当前处理线程
mutex_process.unlock();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
4.实现发送数据的方法的槽函数

void output::work()
{
while (1)
{
qDebug()<<"output3";
mutex_input.lock();
condition_input.wakeOne();//唤醒下一次的收线程
mutex_input.unlock();
mutex_output.lock();
condition_output.wait(&mutex_output);//睡眠当前的发线程
mutex_output.unlock();
}
}

void output::threadSleep()
{
qDebug()<<QThread::currentThreadId();
mutex_output.lock();
condition_output.wait(&mutex_output);//睡眠当前的发线程
mutex_output.unlock();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
5.main函数中的最终实现

input_thread = new inputThread();
process_thread = new processThread();
out_thread = new outputThread();

//开启线程
input_thread ->start();
process_thread ->start();
out_thread ->start();

//生成方法对象
data_input = new input();
data_process = new process();
data_output = new output();
//移入线程
data_input->moveToThread(input_thread);
data_process->moveToThread(process_thread);
data_output->moveToThread(out_thread);
//使得数据处理和数据发送线程睡眠的槽函数和按键1的点击信号关联
connect(this,SIGNAL(click1()),data_process,SLOT(threadSleep()));
connect(this,SIGNAL(click1()),data_output,SLOT(threadSleep()));
//使得三个线程的work槽函数和按键1的点击信号关联
connect(this,SIGNAL(click2()),data_input,SLOT(work()));
connect(this,SIGNAL(click2()),data_process,SLOT(work()));
connect(this,SIGNAL(click2()),data_output,SLOT(work()));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
使用方法
先触发click1信号,使得数据处理线程和数据发送线程睡眠;再触发click2信号,使得三个线程按照既定的顺序ABC循环执行。

输出结果
input1
process2
output3
input1
process2
output3
input1
process2
output3
input1
process2
output3
1
2
3
4
5
6
7
8
9
10
11
12
注意事项
线程类的run函数里记得加exec(),使得线程常驻
---------------------
作者:蜗牛在听雨
来源:CSDN
原文:https://blog.csdn.net/omg_orange/article/details/82388243
版权声明:本文为博主原创文章,转载请附上博文链接!

Qt 控制线程的顺序执行(使用QWaitCondition,并且线程类的run函数里记得加exec(),使得线程常驻)的更多相关文章

  1. C#之使用AutoResetEvent实现线程的顺序执行

    前几天一朋友问我如何实现线程的顺序执行,说真的,虽然看过CLR这本书,也把线程部分拜读了两遍,但是这个问题出来之后还是没有一个思路.今天在搜索资料的时候无意中再次看到AutoResetEvent这个东 ...

  2. 【Java并发】线程的顺序执行

    /** * 问题:有线程a.b.c,如何让它们顺序执行? * 方式一:可用Join()方法实现 * 方式二:可用newSingleThreadExecutor() * Created by Smile ...

  3. Qt QThread两种方式的使用:1-继承QThread重写run函数; 2- 继承QObject并moveToThread && 消息和槽在线程和依附线程间的传递

    2019年08月18日起笔 方式一:继承QThread重写run函数 MyThread.h ----------------------------------- ... class MyThread ...

  4. 3.创建线程的第二种写法,继承threading.Tread类,重写run方法

    #创建线程的第二种写法 #1.自定义一个类 #2.继承Thread #3.重写run()方法 import threading,time,random class MyThread(threading ...

  5. 三个线程abc顺序执行

    1.使用synchronized悲观锁(秋招阿里的一个笔试题,应该写的比较复杂,然后就没有然后了o(╥﹏╥)o) public class ThreadThreadp { private int fl ...

  6. java 多线程 实现多个线程的顺序执行

    场景 编写一个程序,启动三个线程,三个线程的name分别是A,B,C:,每个线程将自己的ID值在屏幕上打印5遍,打印顺序是ABCABC... 使用 synchronized 实现 public cla ...

  7. Jmeter-Critical Section Controller(临界区控制器)(还没看,是一个控制请求按顺序执行的东东)

    The Critical Section Controller ensures that its children elements (samplers/controllers, etc.) will ...

  8. Java中如何保证线程顺序执行

    只要了解过多线程,我们就知道线程开始的顺序跟执行的顺序是不一样的.如果只是创建三个线程然后执行,最后的执行顺序是不可预期的.这是因为在创建完线程之后,线程执行的开始时间取决于CPU何时分配时间片,线程 ...

  9. Python流程控制-1 顺序执行

    流程控制指的是代码运行逻辑.分支走向.循环控制,是真正体现我们程序执行顺序的操作.流程控制一般分为顺序执行.条件判断和循环控制. 顺序执行 Python代码在执行过程中,遵循下面的基本原则: 普通语句 ...

随机推荐

  1. 其它系统与domino系统单点登录的实现方式

     其它系统与domino系统单点登录的实现方式 [背景] 随着企业中业务不断增多,用户处理不同的业务则须要频繁的切换不同的系统进行操作.而用户则须要记住各个系统的username.password ...

  2. perl 面向对象编程

    今天看到一个perl面向对象编程的例子,充分体现了如何对数据进行封装: 自己模仿写一个读取配置文件的例子, 配置文件的内容如下 samtools_binary = /usr/bin/samtools ...

  3. jQuery-处理css样式

    1.css方法 获取匹配元素集合中的第一个元素的样式属性的值 或 设置每个匹配元素的一个或多个CSS属性 1)获取并设置单个css值 jQuery对象.css('css属性'); jQuery对象.c ...

  4. C# SerialPortHelper类

    using System; using System.IO.Ports; class SerialPortHelper { private long _receiveByteCount = 0, _s ...

  5. sourcetree管理git

    下载地址: https://www.sourcetreeapp.com/ 跳过注册: 到注册登录页面打开文件目录%LocalAppData%\Atlassian\SourceTree\ 会发现有个文件 ...

  6. Linux安装php运行环境

    安装apache: yum install httpd httpd-devel  启动apache: /etc/init.d/httpd start 此时输入服务器的IP地址,应该看到apache的服 ...

  7. Java中的各种加密算法

    Java中为我们提供了丰富的加密技术,可以基本的分为单向加密和非对称加密 1.单向加密算法 单向加密算法主要用来验证数据传输的过程中,是否被篡改过. BASE64 严格地说,属于编码格式,而非加密算法 ...

  8. ubuntu wine-qq安装

    1.添加PPA sudo add-apt-repository ppa:ubuntu-wine/ppa 2.更新列表 sudo apt-get update 3.安装Wine sudo apt-get ...

  9. ch4-持久存储

    1.处理数据和打印 man = [] other = [] try: data = open('sketch.txt') for each_line in data: try: (role, line ...

  10. View的setTag()与getTag()方法使用

    通常我们是用findViewById()方法来取得我们要使用的View控件,不过除了这一种方法之处 ,我们还可以用View中的setTag(Onbect)给View添加一个格外的数据,再用getTag ...