背景
项目中用到多线程,对线程的执行顺序有要求:
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. ubuntu安裝 R RStudio

    sudo apt--i386.deb ref: http://blog.csdn.net/lichangzai/article/details/39376117

  2. Centos下查看和修改网卡Mac地址

    linux/Centos下查看网卡Mac地址,输入命令: #ifconfig -a eth0 Link encap:Ethernet HWaddr 00:e4:56:2E:D8:20 00:e4:56 ...

  3. 10种canvas鼠标光标动画特效

    来源:http://www.sucaihuo.com/js/1780.html demo:http://www.sucaihuo.com/jquery/17/1780/demo/

  4. 解决myeclipse4.1.1对一个表生成映射文件的时候,出现“generating artifacts"的解决!

    很多人在用myeclipse4.1.1对一个表生成映射文件的时候,都出现“generating artifacts"的问题.我也遇到了这个问题,弄得我也很郁闷!看了很多人的帖子后还是无法搞定 ...

  5. Unity5.4新版AssetBundle资源打包

    (1)新版本 唯一打包API Buildpipeline.BuildAssetBundle (2)在资源的Inpector界面最下方可设置该资源的assetbundleName, 每个assetbun ...

  6. C#获取CPU处理器核心数量的方法_C#教程

    https://yq.aliyun.com/ziliao/89096 摘要: 本文讲的是C#获取CPU处理器核心数量的方法_C#教程, 有几条不同的处理器信息,您可以获得有关的信息:物理处理器数量.核 ...

  7. js timestamp与datetime之间的相互转换

    1.  datetime转换成timestamp strdate = "2015-08-09 08:01:36:"; var d = new Date(strdate); var ...

  8. Android弹出Dialog使用举例

    Android详细的对话框AlertDialog.Builder使用方法 7种形式的Android Dialog使用举例 第30章.常见对话框之一AlertDialog(从零开始学Android)

  9. [译] 关于CSS中的float和position

    原文 http://learn.shayhowe.com/advanced-html-css/detailed-css-positioning 当构建页面排版时,有不同的方法可以使用.使用哪一种方法取 ...

  10. c++11——std::function和bind绑定器

    c++11中增加了std::function和std::bind,可更加方便的使用标准库,同时也可方便的进行延时求值. 可调用对象 c++中的可调用对象存在以下几类: (1)函数指针 (2)具有ope ...