QtConcurrent::run:高效并行编程实现方式

一、 QtConcurrent::run简介

QtConcurrent是Qt框架中的一个模块,旨在提供方便且高效的并行编程实现方式。其中QtConcurrent::run是使用最广泛的方法。调用QtConcurrent::run时,将会自动将函数以一个新的线程运行,并将函数返回结果传递回主线程。

QtConcurrent::run的用法简单,仅需传递一个函数指针和函数参数,即可使用多线程的方式运行函数。使用QtConcurrent::run可以充分利用多核处理器,提高程序效率,同时避免了使用底层多线程时的一些容易出现的线程安全问题。

二、 使用QtConcurrent::run进行多线程编程

我们来看一个简单的例子,假设我们需要对一个字符串进行加密处理:


QString encrypt(QString str, int key) {
    for(int i = 0; i < str.length(); ++i) {
        str[i] = str[i] ^ key;
    }
    return str;
}

接下来,我们通过QtConcurrent::run在新线程中运行这个函数:


QFuture future = QtConcurrent::run(encrypt, "hello world", 42);

使用QtConcurrent::run时,它不会占用主线程的时间,而是会自动启用一个新的线程去执行函数,这个新的线程会在后台运行,直到函数执行完毕并返回结果。

在这里我们用QFuture保存异步操作的结果,QFuture表示未来的结果,这个结果可以在需要的时候被获取。

下面,我们通过QFuture对象获取异步操作的结果:


QString result = future.result();

在需要异步操作结果的地方使用future.result()来获取异步操作结果,如果异步操作没有完成,future.result()就会一直等待,直到异步操作完成为止。

三、使用QtConcurrent::run实现线程安全的容器操作

除了简单的函数运算外,QtConcurrent::run还可以用于执行容器的并行操作,比如在多线程中对QList的修改操作。

在多线程中,对容器的修改操作需要考虑到线程安全,以避免出现竞态条件等线程安全问题。一般的解决方法是添加互斥锁,但互斥锁会导致线程的等待与阻塞,降低程序的效率。

使用QtConcurrent::run可以方便地实现线程安全的容器操作,使用QtConcurrent::run时需要将需要并行执行的操作函数写成可重入的函数。

以下是一个使用QtConcurrent::run实现并行容器操作的例子,这里我们实现一个在多线程中并行地对一个QList进行排序的操作。


void sort(QList& list) {
    std::sort(list.begin(), list.end());
}

void parallelSort(QList& list) {
    QVector<QFuture> futures;
    const int threadCount = QThread::idealThreadCount();
    const int chunkSize = list.size() / threadCount;
    int begin = 0, end = chunkSize;
    for(int i = 0; i < threadCount; ++i) {
        if(i == threadCount - 1) {
            end = list.size();
        }
        futures.append(QtConcurrent::run(sort, list.mid(begin, end - begin)));
        begin = end;
        end += chunkSize;
    }
    for(int i = 0; i < futures.size(); ++i) {
        futures[i].waitForFinished();
    }
    std::inplace_merge(list.begin(), list.begin() + chunkSize, list.end());
}

parallelSort函数中,我们将要排序的QList按照QThread::idealThreadCount()的数量进行分割,并将每个子序列交给一个新线程去执行排序操作。

执行完所有子线程后,我们使用std::inplace_merge函数合并所有的排好序的子序列。

四、QtConcurrent::run的使用注意事项

虽然QtConcurrent::run提供了一种方便且高效的多线程编程实现方式,但其也有其适用的范围和使用注意事项:

  1. 线程池内的线程更加倾向于长期存在,不要把耗时很短的任务放进线程池中,可能会导致线程池耗费过多的系统资源,不利于程序性能。
    
    // 不建议写法
    for (int i = 0; i < 100; ++i) {
        QtConcurrent::run([](){ /* do something */ });
    }
    
  2. QtConcurrent::run会在新线程中自动执行函数,但也可以使用QThread手动地创建新线程。
    
    QThread* thread1 = new QThread();
    MyObject* object1 = new MyObject();
    object1->moveToThread(thread1);
    QObject::connect(thread1, &QThread::started, object1, &MyObject::mySlot);
    thread1->start();
    
  3. 使用QtConcurrent::run时需要注意线程安全,避免并发操作数据时出现竞争问题。
  4. QtConcurrent::run可以将函数的返回结果传递到主线程,但是如果异步操作返回的结果需要马上使用,应使用QFuture::result()来等待异步操作的结束并获取结果,否则可能会在异步操作没结束前使用该结果。
    
    QString result = QtConcurrent::run(someFunction, params).result();
    

五、结语

QtConcurrent::run是Qt框架中提供的一种方便、高效的多线程编程实现方式。使用QtConcurrent::run可以避免使用底层多线程时的一些容易出现的线程安全问题,并充分利用多核处理器提高程序效率。

在使用QtConcurrent::run时需要注意线程安全,合理地使用QThread,避免将耗时很短的任务放进线程池中,正确地使用异步的结果等技巧,可以充分发挥QtConcurrent::run的优势。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/244091.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-12 13:00
下一篇 2024-12-12 13:00

相关推荐

  • Python缓存图片的处理方式

    本文将从多个方面详细阐述Python缓存图片的处理方式,包括缓存原理、缓存框架、缓存策略、缓存更新和缓存清除等方面。 一、缓存原理 缓存是一种提高应用程序性能的技术,在网络应用中流…

    编程 2025-04-29
  • Trocket:打造高效可靠的远程控制工具

    如何使用trocket打造高效可靠的远程控制工具?本文将从以下几个方面进行详细的阐述。 一、安装和使用trocket trocket是一个基于Python实现的远程控制工具,使用时…

    编程 2025-04-28
  • Python在线编辑器的优势与实现方式

    Python在线编辑器是Python语言爱好者的重要工具之一,它可以让用户方便快捷的在线编码、调试和分享代码,无需在本地安装Python环境。本文将从多个方面对Python在线编辑…

    编程 2025-04-28
  • Python生成列表最高效的方法

    本文主要介绍在Python中生成列表最高效的方法,涉及到列表生成式、range函数、map函数以及ITertools模块等多种方法。 一、列表生成式 列表生成式是Python中最常…

    编程 2025-04-28
  • Java表单提交方式

    Java表单提交有两种方式,分别是get和post。下面我们将从以下几个方面详细阐述这两种方式。 一、get方式 1、什么是get方式 在get方式下,表单的数据会以查询字符串的形…

    编程 2025-04-27
  • TFN MR56:高效可靠的网络环境管理工具

    本文将从多个方面深入阐述TFN MR56的作用、特点、使用方法以及优点,为读者全面介绍这一高效可靠的网络环境管理工具。 一、简介 TFN MR56是一款多功能的网络环境管理工具,可…

    编程 2025-04-27
  • 用Pythonic的方式编写高效代码

    Pythonic是一种编程哲学,它强调Python编程风格的简单、清晰、优雅和明确。Python应该描述为一种语言而不是一种编程语言。Pythonic的编程方式不仅可以使我们在编码…

    编程 2025-04-27
  • Java多版本支持实现方式

    本文将从以下几个方面阐述如何实现Java多版本支持,并给出可行的代码示例。 一、多版本Java环境概述 Java是一门跨平台的编程语言,但是在不同的应用场景下,可能需要使用不同版本…

    编程 2025-04-27
  • SpringBoot Get方式请求传参用法介绍

    本文将从以下多个方面对SpringBoot Get方式请求传参做详细的阐述,包括URL传参、路径传参、请求头传参、请求体传参等,帮助读者更加深入地了解Get请求方式下传参的相关知识…

    编程 2025-04-27
  • Python生成10万条数据的高效方法

    本文将从以下几个方面探讨如何高效地生成Python中的10万条数据: 一、使用Python内置函数生成数据 Python提供了许多内置函数可以用来生成数据,例如range()函数可…

    编程 2025-04-27

发表回复

登录后才能评论