QRunnable结合QThreadPoll实现多线程

前面的博文中,我们讲过QtConcurrent模块,该模块是Qt中实现并发编程的高级API接口,而QRunnable结合QThreadPoll和QThread都是Qt中与并发编程相关的低级接口。今天我们先来看QRunnable和QThreadPool。

QRunnable类在Qt中是所有可运行对象的基类,代表了由run()函数表示的一个任务或一段要执行的代码。我们一般使用该类和QThreadPool来在另一个独立的线程中执行该代码。并且,如果QRunnable对象的autoDelete()设为true的话,QThreadPool会在run()运行结束后自动删除该对象。

下面,我们写一个例子,来使用一下该类。

新建一个Qt控制台程序,然后写一个派生自QRunnable的类,并重新实现其中的纯虚函数run()即可。


    
    
  1. #ifndef RUNNABLE_H
  2. #define RUNNABLE_H
  3. #include <QRunnable>
  4. class Runnable : public QRunnable
  5. {
  6. public:
  7. Runnable();
  8. void run();
  9. };
  10. #endif // RUNNABLE_H
  11. #include “runnable.h”
  12. #include <QDebug>
  13. #include <QThread>
  14. Runnable::Runnable()
  15. {
  16. }
  17. void Runnable::run()
  18. {
  19. qDebug() << “child thread id: “ << QThread::currentThreadId();
  20. int i = 10;
  21. while(i–)
  22. {
  23. qDebug() << QString( “hello world %1”).arg(i);
  24. }
  25. }


然后在main函数中,使用QThreadPool来启动一个Runnable对象,在独立的线程中运行。


    
    
  1. #include <QCoreApplication>
  2. #include "runnable.h"
  3. #include <QThreadPool>
  4. #include <QDebug>
  5. #include <QThread>
  6. int main(int argc, char *argv[])
  7. {
  8. QCoreApplication a(argc, argv);
  9. qDebug() << "main thread id: " << QThread::currentThreadId();
  10. Runnable *r = new Runnable();
  11. QThreadPool::globalInstance()->start(r);
  12. //QThreadPool::globalInstance()->waitForDone();
  13. qDebug() << "end";
  14. return a.exec();
  15. }
其运行结果如下:



根据打印的thread ID可知,这些输出是由两个的线程的输出的,并且“end”先与子线程输出。如果我们想等到子线程运行完成再输出“end”,只需将代码中注释的那句打开即可。

运行结果如下:


此时,“end”就在子线程运行完成后才输出,即我们等待了线程的结束。

我们还可以实现一个析构函数,来验证QThreadPool是否为我们释放了Runnable对象。


    
    
  1. Runnable::~Runnable()
  2. {
  3. qDebug() << "deleted";
  4. }
在此执行程序,输出如下:



因为QRunnable的autoDelete属性默认为true,所以QThreadPool会在run()函数运行结束后,自动帮我们删除了Runnable对象。如果我们在main函数中,创建出Runnable对象后,修改该属性为false,那么将看不到“deleted”,因为此时Runnable对象的释放工作,将由我们自己来负责。


            </div>

前面的博文中,我们讲过QtConcurrent模块,该模块是Qt中实现并发编程的高级API接口,而QRunnable结合QThreadPoll和QThread都是Qt中与并发编程相关的低级接口。今天我们先来看QRunnable和QThreadPool。

QRunnable类在Qt中是所有可运行对象的基类,代表了由run()函数表示的一个任务或一段要执行的代码。我们一般使用该类和QThreadPool来在另一个独立的线程中执行该代码。并且,如果QRunnable对象的autoDelete()设为true的话,QThreadPool会在run()运行结束后自动删除该对象。

下面,我们写一个例子,来使用一下该类。

新建一个Qt控制台程序,然后写一个派生自QRunnable的类,并重新实现其中的纯虚函数run()即可。


  
  
  1. #ifndef RUNNABLE_H
  2. #define RUNNABLE_H
  3. #include <QRunnable>
  4. class Runnable : public QRunnable
  5. {
  6. public:
  7. Runnable();
  8. void run();
  9. };
  10. #endif // RUNNABLE_H
  11. #include “runnable.h”
  12. #include <QDebug>
  13. #include <QThread>
  14. Runnable::Runnable()
  15. {
  16. }
  17. void Runnable::run()
  18. {
  19. qDebug() << “child thread id: “ << QThread::currentThreadId();
  20. int i = 10;
  21. while(i–)
  22. {
  23. qDebug() << QString( “hello world %1”).arg(i);
  24. }
  25. }


然后在main函数中,使用QThreadPool来启动一个Runnable对象,在独立的线程中运行。


  
  
  1. #include <QCoreApplication>
  2. #include "runnable.h"
  3. #include <QThreadPool>
  4. #include <QDebug>
  5. #include <QThread>
  6. int main(int argc, char *argv[])
  7. {
  8. QCoreApplication a(argc, argv);
  9. qDebug() << "main thread id: " << QThread::currentThreadId();
  10. Runnable *r = new Runnable();
  11. QThreadPool::globalInstance()->start(r);
  12. //QThreadPool::globalInstance()->waitForDone();
  13. qDebug() << "end";
  14. return a.exec();
  15. }
其运行结果如下:



根据打印的thread ID可知,这些输出是由两个的线程的输出的,并且“end”先与子线程输出。如果我们想等到子线程运行完成再输出“end”,只需将代码中注释的那句打开即可。

运行结果如下:


此时,“end”就在子线程运行完成后才输出,即我们等待了线程的结束。

我们还可以实现一个析构函数,来验证QThreadPool是否为我们释放了Runnable对象。


  
  
  1. Runnable::~Runnable()
  2. {
  3. qDebug() << "deleted";
  4. }
在此执行程序,输出如下:



因为QRunnable的autoDelete属性默认为true,所以QThreadPool会在run()函数运行结束后,自动帮我们删除了Runnable对象。如果我们在main函数中,创建出Runnable对象后,修改该属性为false,那么将看不到“deleted”,因为此时Runnable对象的释放工作,将由我们自己来负责。


            </div>

猜你喜欢

转载自blog.csdn.net/tt_137062185/article/details/81080102