QtConcurren导读

QtConcurrent提供了编写多线程程序的高级api,也即不使用低级线程原语,而其他实现多线程的方式,例如子类化QThread、QObject::moveToThread()、子类化QRunnable对于共享数据的保护都要使用低级线程原语,这无疑是要非常小心的。
此外,根据Qt文档的描述:Programs written with QtConcurrent automatically adjust the number of threads used according to the number of processor cores available. This means that applications written today will continue to scale when deployed on multi-core systems in the future.,也就是说QtConcurrent可以根据机器的cpu自动调整线程数,以至于部署在其他机器上不用担心这方面的问题。
注:低级线程原语指的是:mutexes(互斥锁), read-write locks(读写锁), wait conditions(等待条件), or semaphores(信号量)

.pro 工程文件

使用 QtConcurrent 模块,需要在 .pro 中添加: QT += concurrent

QT += concurrent widgets
CONFIG += console
 
SOURCES += main.cpp 

QT多线程之QtConcurrent::run()

//在新的线程中调用普通函数 
template <typename T> QFuture<T> QtConcurrent::run(Function function, ...) 
//使用线程池中的线程调用普通函数 
template <typename T> QFuture<T> QtConcurrent::run(QThreadPool *pool, Function function, ...) 
//在新的线程里调用成员函数 有多个重载实现不同的参数个数 
template <typename T> QFuture<T> QtConcurrent::run(className *obejct, Function function, ...)

这些模板都有多个重载,支持带参数函数,切可以带多个参数。
QFuture 也是一个模板类,它可以监控线程的运行状态有,并可以获取在另一个线程中运行的函数的返回值,返回值通过调用result()函数获取。
需要注意的是获取返回值之前,最好先调用waitForFinished()保证线程执行完毕。

示例

#pragma once
#include <QtCore/QObject>
#include <QtConcurrent/QtConcurrent>
#include <QtCore/QThread>
class ThreadTest {
public:
    ThreadTest();
    ~ThreadTest() = default;

public:
    void anotherThread();
    std::string anotherThreadReturn();
};

.cpp

#include "QtThreadTest.h"
#include <iostream>
#include <QFuture>
void normalFunction() {
    std::cerr << "Normal function thread ID: " << QThread::currentThreadId() << std::endl;
}
ThreadTest::ThreadTest()
{
    std::cerr << "main thread ID: " << QThread::currentThreadId() << std::endl;
    QtConcurrent::run(normalFunction);
    QFuture<void> future = QtConcurrent::run(this, &ThreadTest::anotherThread);
    QFuture<std::string> future1 = QtConcurrent::run(this, &ThreadTest::anotherThreadReturn);
    future.waitForFinished();
    future1.waitForFinished();
    std::cerr << "anotherThreadReturn result: " << future1.result() << std::endl;
}
void ThreadTest::anotherThread()
{
    std::cerr << "Another thread ID: " << QThread::currentThreadId() << std::endl;
}
std::string ThreadTest::anotherThreadReturn()
{
    std::cerr << "Another return thread ID: " << QThread::currentThreadId() << std::endl;
    return "This is result";
}

总结

  1. 调用run()
    之后,函数不一定会被立即执行,如果有多个run()被调用,函数的调用顺序不一定是run()的调用顺序,这些都和线程的调度有关系。
  2. run(function) 实际上等价于run(QThreadPool::globalInstance(),function)
    如果只是简单的想在其他线程中调用某个函数,不需要复杂的数据同步,那么QtConcurrent::run()
    相比其他实现多线程的方式绝对是不二之选。
06-29 10:09