zoukankan      html  css  js  c++  java
  • Qt 控制线程的顺序执行(使用QWaitCondition,并且线程类的run函数里记得加exec(),使得线程常驻)

    背景
    项目中用到多线程,对线程的执行顺序有要求:
    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
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    Python一些常用模块
    八、线程和进程
    七、Selenium与phantomJS----------动态页面模拟点击、网站模拟登录
    一、scrapy的下载安装---Windows(安装软件太让我伤心了)
    六、BeautifulSoup4------自动登录网站(手动版)
    五、XML与xpath--------------爬取美女图片
    四、正则表达式re模块
    三、Requests库的使用
    二、urllib进阶
    一、爬虫的基本体系和urllib的基本使用
  • 原文地址:https://www.cnblogs.com/findumars/p/10344546.html
Copyright © 2011-2022 走看看