QT多线程(主动挂起线程)

简介: QT多线程(主动挂起线程)

前言

本篇文章来讲解一下QT中如何主动挂起线程,在不想让一个线程运行的时候我们应该如何让线程挂起呢?我们都知道使用sleep函数可以让线程挂起一段时间,但是一段时间过后线程又继续运行,那么有什么方法可以让线程在特定条件下挂起,特定条件下运行吗?


一、线程的挂起态

在Qt中,线程可以通过调用 QThread::sleep() 函数进入挂起状态。QThread::sleep() 函数会导致线程在指定的毫秒数内休眠,进入睡眠状态,等待指定的时间后再继续运行。

线程的挂起状态常用于等待某个事件的发生,比如等待信号的到来、等待定时器的触发、等待文件的读写操作完成等。当线程挂起时,它会主动放弃 CPU 的时间片,以节约系统资源。

在Qt中,还可以通过将线程阻塞在某个对象上来实现挂起状态。比如,可以通过调用 QWaitCondition::wait() 函数将线程阻塞在某个条件变量上,等待其他线程对该条件变量发出信号后再继续执行。

需要注意的是,线程在挂起状态下不会停止,仍然会占用系统资源。因此,在使用线程挂起功能时,需要确保挂起的时间不会过长,以避免降低系统的性能和可靠性。

此外,需要注意线程挂起状态的使用场景和时机。线程挂起过程中不会处理任何事件,包括定时器事件、键盘事件、鼠标事件等,因此,如果在线程中进行长时间的阻塞或挂起,可能会导致 UI 界面无响应,影响用户体验。因此,建议在非必要情况下尽量避免使用线程挂起功能,或者通过线程间通信等机制来替代线程挂起。

二、QWaitCondition

在Qt中,QWaitCondition 是一个用于线程同步的对象,它可以让一个线程等待或者阻塞在一个特定的条件上,直到被其他线程唤醒。

QWaitCondition 的使用通常涉及以下三个对象:

条件变量(QWaitCondition),用来等待和唤醒线程。

互斥锁(QMutex),用来保护条件变量。

通知对象(QMutexLocker),用来通知和等待。

使用 QWaitCondition 时需要注意以下几点:

线程只有在持有相应的互斥锁时才能调用 QWaitCondition::wait() 函数;在阻塞期间会释放互斥锁并进入挂起状态。

发送信号之前,必须先获取相应的互斥锁,否则线程不会得到通知。

通过调用 QWaitCondition::wakeOne() 可以唤醒单个线程,调用 QWaitCondition::wakeAll() 可以唤醒所有等待的线程。

等待时,建议使用 while 循环来检查条件是否满足,防止条件非常容易发生变化的情况下出现误唤醒的问题。


三、示例代码

这段程序主要是实现了主线程既可以唤醒ThreadA线程又可以将ThreadA线程挂起的功能。

#include <QtCore/QCoreApplication>
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <QDebug>
QMutex g_mutex;
QWaitCondition g_waitcondition;
bool ConditionMet = true;
class ThreadA : public QThread
{
protected:
    void run()
    {
        qDebug() << "Thread Begin";
        while(1)
        {
            g_mutex.lock();            
            while(!ConditionMet)
            {
                g_waitcondition.wait(&g_mutex);//先释放锁,再获取锁
                break;
            }
            qDebug() << "ThreadA";
            g_mutex.unlock();
            sleep(1);
        }
        qDebug() << "Thread End";
    }
};
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    ThreadA t1;
    t1.start();
    int i = 0;
    while(1)
    {
        qDebug() << "Main Thread";
        i++;
        if(i == 5)
        {
            qDebug() << "ThreadA stop";
            g_mutex.lock();
            ConditionMet = false;
            g_mutex.unlock();
        }
        else if(i == 10)
        {
            qDebug() << "wake ThreadA";
            i = 0;
            g_mutex.lock();
            ConditionMet = true;
            g_waitcondition.wakeOne();
            g_mutex.unlock();
        }
        QThread::sleep(1);
    }
    return a.exec();
}

总结

QWaitCondition 在多线程编程中具有重要的作用,可以帮助实现线程之间的同步和通信,也是Qt中高效使用多线程的关键。

相关文章
|
1月前
|
存储 监控 Java
Java多线程优化:提高线程池性能的技巧与实践
Java多线程优化:提高线程池性能的技巧与实践
57 1
|
7天前
|
Java Spring
spring多线程实现+合理设置最大线程数和核心线程数
本文介绍了手动设置线程池时的最大线程数和核心线程数配置方法,建议根据CPU核数及程序类型(CPU密集型或IO密集型)来合理设定。对于IO密集型,核心线程数设为CPU核数的两倍;CPU密集型则设为CPU核数加一。此外,还讨论了`maxPoolSize`、`keepAliveTime`、`allowCoreThreadTimeout`和`queueCapacity`等参数的设置策略,以确保线程池高效稳定运行。
52 10
spring多线程实现+合理设置最大线程数和核心线程数
|
15天前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android多线程编程的重要性及其实现方法,涵盖了基本概念、常见线程类型(如主线程、工作线程)以及多种多线程实现方式(如`Thread`、`HandlerThread`、`Executors`、Kotlin协程等)。通过合理的多线程管理,可大幅提升应用性能和用户体验。
28 15
一个Android App最少有几个线程?实现多线程的方式有哪些?
|
1天前
|
Python
5-5|python开启多线程入口必须在main,从python线程(而不是main线程)启动pyQt线程有什么坏处?...
5-5|python开启多线程入口必须在main,从python线程(而不是main线程)启动pyQt线程有什么坏处?...
|
17天前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android应用开发中的多线程编程,涵盖基本概念、常见实现方式及最佳实践。主要内容包括主线程与工作线程的作用、多线程的多种实现方法(如 `Thread`、`HandlerThread`、`Executors` 和 Kotlin 协程),以及如何避免内存泄漏和合理使用线程池。通过有效的多线程管理,可以显著提升应用性能和用户体验。
37 10
|
24天前
|
存储 Ubuntu Linux
C语言 多线程编程(1) 初识线程和条件变量
本文档详细介绍了多线程的概念、相关命令及线程的操作方法。首先解释了线程的定义及其与进程的关系,接着对比了线程与进程的区别。随后介绍了如何在 Linux 系统中使用 `pidstat`、`top` 和 `ps` 命令查看线程信息。文档还探讨了多进程和多线程模式各自的优缺点及适用场景,并详细讲解了如何使用 POSIX 线程库创建、退出、等待和取消线程。此外,还介绍了线程分离的概念和方法,并提供了多个示例代码帮助理解。最后,深入探讨了线程间的通讯机制、互斥锁和条件变量的使用,通过具体示例展示了如何实现生产者与消费者的同步模型。
|
1月前
|
监控 安全 Java
Java多线程调试技巧:如何定位和解决线程安全问题
Java多线程调试技巧:如何定位和解决线程安全问题
76 2
|
1月前
|
存储 安全 Unix
并发编程基础:使用POSIX线程(pthread)进行多线程编程。
并发编程基础:使用POSIX线程(pthread)进行多线程编程。
56 0
|
1月前
|
存储 安全 Java
【多线程面试题十七】、如果不使用synchronized和Lock,如何保证线程安全?
这篇文章探讨了在不使用`synchronized`和`Lock`的情况下保证线程安全的方法,包括使用`volatile`关键字、原子变量、线程本地存储(`ThreadLocal`)以及设计不可变对象。