zoukankan      html  css  js  c++  java
  • Qt之多线程

    源地址:http://blog.csdn.net/liuhongwei123888/article/details/6072320

    Qt 是一种基于 C++ 的跨平台 GUI 系统,能够提供给用户构造图形用户界面的强大功能。为了满足用户构造复杂图形界面系统的需求,Qt 提供了丰富的多线程编程支持。Qt 主要从三个方面对多线程编程提供支持:一、构造了一些基本的与平台无关的线程类;二、提交用户自定义事件的 Thread-safe 方式;三、多种线程间同步机制,如信号量,全局锁。

    1、QThread

           QThread提供了与平台无关的线程。一个QThread代表单独运行于程序的线程。它与进程中的其他线程共享数据,在多任务操作系统中单独运行。线程使用run()方法开始执行,在run()方法中调用exec()开始事件循环。我们可以通过继承QThread并且重写run()函数编写一个线程。例如:

    [cpp] view plaincopy
     
    1. //mythread.h  
    2. #ifndef MYTHREAD_H  
    3. #define MYTHREAD_H  
    4. #include <QThread>  
    5. class MyThread : public QThread  
    6. {  
    7. public:  
    8.     MyThread();  
    9.     MyThread(int count);  
    10.     void run();  
    11. private:  
    12.     int count;  
    13. };  
    14. #endif // MYTHREAD_H  
    [cpp] view plaincopy
     
    1. //mythread.cpp  
    2. #include "mythread.h"  
    3. #include "QThread"  
    4. #include <QDebug>  
    5. MyThread::MyThread()  
    6. {  
    7. }  
    8. MyThread::MyThread(int count)  
    9. {  
    10.     this->count = count;  
    11. }  
    12. void MyThread::run()  
    13. {  
    14.     while(count<20000)//为了查看结果尽量设置大一些  
    15.     {  
    16.         qDebug()<< QThread::currentThread()->objectName()<<this->count++;  
    17.     }  
    18. }  
    [c-sharp] view plaincopy
     
    1. //main.cpp  
    2. #include <QtCore/QCoreApplication>  
    3. #include "mythread.h"  
    4. #include <QDebug>  
    5. int main(int argc, char *argv[])  
    6. {  
    7.     QCoreApplication a(argc, argv);  
    8.     qDebug()<< "Main Start";  
    9.     MyThread myThread1(0);  
    10.     myThread1.setObjectName("MyThread1");  
    11.     myThread1.start();  
    12.     MyThread myThread2(0);  
    13.     myThread2.setObjectName("MyThread2");  
    14.     myThread2.start();  
    15.     int c = 0;  
    16.     while(c < 20000)//为了查看结果尽量设置大一些  
    17.     {  
    18.         qDebug()<< "Main Thread"<< c++;  
    19.     }  
    20.     return a.exec();  
    21. }  

    在main函数中我定义了两个线程,并分别设置了线程名称。运行过程中有三个线程会可能同时运行。主函数线程,myThread1线程,myThread2线程。可以从运行结果看出:

    g

    Main Start 
    Main Thread 0 
    Main Thread 1 
    Main Thread 2 
    Main Thread 3 
    Main Thread 4 
    Main Thread 5

    ....

    Main Thread 1040 
    Main Thread 1041 
    Main Thread 1042 
    Main Thread 1043 
    Main Thread 1044 
    "MyThread2" 0 
    "MyThread2" 1 
    "MyThread2" 2 
    "MyThread2" 3 
    "MyThread2" 4 
    "MyThread2" 5 
    "MyThread2" 6

    .....

    "MyThread2" 1158 
    "MyThread2" 1159 
    "MyThread2" 1160 
    "MyThread2" 1161 
    "MyThread2" 1162 
    "MyThread1" 0 
    "MyThread1" 1 
    "MyThread1" 2 
    "MyThread1" 3 
    "MyThread1" 4 
    "MyThread1" 5

    .......

    Main Thread 19990 
    Main Thread 19991 
    Main Thread 19992 
    Main Thread 19993 
    Main Thread 19994 
    Main Thread 19995 
    Main Thread 19996 
    Main Thread 19997 
    Main Thread 19998 
    Main Thread 19999

    QThread包含一个枚举类型
    enum    Priority { IdlePriority, LowestPriority, LowPriority, NormalPriority, ..., InheritPriority } 这个枚举类型表示操作系统如何应安排新创建的线程
    QThread::IdlePriority    0    安排只是CPU空闲时在运行
    QThread::LowestPriority    1    安排最低优先级
    QThread::LowPriority    2    安排低优先级
    QThread::NormalPriority    3    安排正常优先级
    QThread::HighPriority    4    安排高优先级
    QThread::HighestPriority    5    安排高于最高.
    QThread::TimeCriticalPriority    6    尽可能安排.
    QThread::InheritPriority    7    安排使用继承父类优先级(默认)

    公共方法:
    QThread ( QObject * parent = 0 )    构造函数,这个线程知道调用它的start函数时才会执行
    ~QThread ()                析构函数
    void    exit ( int returnCode = 0 )    调用此方法后,线程将退出事件循环并且返回从调用的QEventLoop::exec()的一个返回值
    bool    isFinished () const        返回线程是否已完成
    bool    isRunning () const        返回线程是否正在运行
    Priority    priority () const    返回线程的优先级.如果线程没有运行,将返回InheritPriority
    void    setPriority ( Priority priority )  为正在运行的线程设置优先级,如果线程未运行,将不做任何操作,立即返回.
    void    setStackSize ( uint stackSize )    设置线程栈的大小的最大值,如果在线程中进行递归调用,那么可以通过增加堆得大小来保证递归不会溢出。
    uint    stackSize () const        返回当前线程栈的最大值
    bool    wait ( unsigned long time = ULONG_MAX )阻塞线程直到线程结束运行或Time已经过去

    槽:
    void    quit ()        退出事件循环,等同于调用线程的exit(0),如果线程没有事件循环则什么也不做。
    void    start ( Priority priority = InheritPriority )开始执行线程
    void    terminate ()    终止线程,线程是否立即被终止,依赖于操作系统.警告:这个函数是危险地,不被鼓励使用

    信号:
    void    finished ()    当线程结束运行时此信号被发射
    void    started ()    当线程开始运行时此信号被发射
    void    terminated ()    当线程被终止时此信号被发射

    静态成员:
    QThread *    currentThread ()    返回指向当前线程的指针
    Qt::HANDLE    currentThreadId ()    返回当前线程的句柄
    int    idealThreadCount ()        返回当前操作系统能运行线程的数量    
    void    yieldCurrentThread ()        让出CPU给其他线程,对于运行哪个线程完全决定于操作系统。

    2、QRunnable

           QRunable是所有可运行对象的基类。代表需要执行的一个任务或一段代码的接口。可以通过QThreadPool单独执行线程。QThreadPool可以自动删除QRunable如果此可运行对象的autoDelete()方法返回ture的话。我们可以使用setAutoDelete()函数设置auto-deletion标识.
    总之QRunnable提供了简洁有效的可运行对象的创建
          优点: 创建过程简洁, 使用方便, 配合着自身的autoDelete特性, 有点“招之即来, 挥之即去”的感觉.
          缺点: 无法实时提供自身的运行状态.

    3、QThreadPool

          线程池,用于管理一个线程的集和。

          线程池用于管理和回收线程对象以减少程序中创建线程的花费。

          每个Qt应用都有一个全局的QThreadPool对象,通过QThreadPool::globalInstance()获取


    属性:
    activeThreadCount : const int    线程池中活动的线程个数
    expiryTimeout : int        线程经过expiryTimeout未被使用将被认为expired并且exit。这种线程可以重新被restart.默认过期时间是30000毫秒即30秒。如果过期时间设置为负的,那么被创建的线程将永远不会exit直到线程池销毁。设置过期时间不会影响到已经在运行的线程。只有新创建的线程使用这个过期时间。因此推荐在创建线程池后立即设置过期时间.
    maxThreadCount : int        线程池中允许最大的线程数量。线程池最少允许一个线程,即使这个值被设置为0或负数.默认的最大线程数量是QThread::idealThreadCount()

    公共方法:
    QThreadPool ( QObject * parent = 0 )    
    ~QThreadPool ()
    int    activeThreadCount () const    返回activeThreadCount属性值
    int    expiryTimeout () const        返回expiryTimeout属性值
    int    maxThreadCount () const        返回maxThreadCount属性值
    void    releaseThread ()
    void    reserveThread ()    存储一个线程,
    void    setExpiryTimeout ( int expiryTimeout )
    void    setMaxThreadCount ( int maxThreadCount )
    void    start ( QRunnable * runnable, int priority = 0 )    存储一个线程并且运行可执行对象并且将可执行对象加入到运行队列中,如果这个线程没有使当前线程数超过最大线程数。
    bool    tryStart ( QRunnable * runnable )    尝试存储一个线程并且运行可执行对象。如果没有这时没有时间片可以运行线程,那么这个方法将什么也不做。否则这个可执行对象线程将使用一个可运行线程立即运行。
    void    waitForDone ()    等待所有线程退出,并且移除所有线程池中线程.

    静态函数
    QThreadPool * QThreadPool::globalInstance ()    获取全局线程对象

    QThreadPool::globalInstance()->start(Runable实例);

  • 相关阅读:
    为什么不直接使用socket ,还要定义一个新的websocket 的呢
    js-权威指南-Web套接字
    CSS-蜂窝状展示区域(多个六边形)的一种实现方式
    MQTT入门介绍
    【珍惜时间】vuepro
    搭建react的vw架构时候报 Cannot load preset "advanced".
    跟我一起使用create-react-app脚手架搭建vw-layout解决方案
    【珍惜时间】iReport
    vue中 给router-view 组件的 绑定 key 的原因
    SQL Server Index详解
  • 原文地址:https://www.cnblogs.com/lanye/p/3821799.html
Copyright © 2011-2022 走看看