背景
项目中用到多线程,对线程的执行顺序有要求:
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. hunnu--11547--你的组合数学学得怎样?

    你的组合数学学得怎样?  Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB Total submit users: ...

  2. BinarySearchTree二叉搜索树的实现

    /* 二叉搜索树(Binary Search Tree),(又:二叉查找树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; ...

  3. MFC中控件添加了变量后修改

    新增一个变量这个变量存在于两个位置,一个是头文件中项目名+Dlg.h文件,另一个是源文件中项目名+Dlg.cpp文件

  4. 在工程名.h头文件中写public:

    class CaccessimageApp : public CWinApp { public: _ConnectionPtr m_pConnection; CaccessimageApp(); // ...

  5. maven 配置多模块项目 pom modules

    所有用Maven管理的真实的项目都应该是分模块的,每个模块都对应着一个pom.xml.它们之间通过继承和聚合(也称作多模块,multi-module)相互关联.那么,为什么要这么做呢?我们明明在开发一 ...

  6. 查看当前mysql数据库实例中,支持的字符集有哪些,或者是否支持某个特定字符集

    需求描述: 查看当前mysql实例中支持哪些字符集,过滤特定的字符集 操作过程: 1.通过show character set来进行查看 mysql> show character set; + ...

  7. ubis文件系统的制作

    在linux-2.6.27以前,谈到Flash文件系统,大家很多时候多会想到cramfs.jffs2.yaffs2等文件系统.它们也都是基于文件系统+mtd+flash设备的架构.linux-2.6. ...

  8. Java精选笔记_Java入门

    Java概述 什么是Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言 JavaSE标准版 是为开发普通桌面和商务应用程序提供的解决方案 JavaEE企业版 是为开发企业级应用程序提供的解 ...

  9. swift - UIButton 的用法

    1,按钮的创建 (1)按钮有下面四种类型: contactAdd:前面带“+”图标按钮,默认文字颜色为蓝色,有触摸时的高亮效果 detailDisclosure:前面带“!”图标按钮,默认文字颜色为蓝 ...

  10. docker 配置文件:/etc/docker/daemon.json

    /etc/docker/daemon.json 是 docker 的配置文件,默认是没有的,需要我们手动创建,可配置项如下: [root@localhost ~]$ vim /etc/docker/d ...