iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >Qt 中开启线程的多种方式小结
  • 102
分享到

Qt 中开启线程的多种方式小结

2024-04-02 19:04:59 102人浏览 泡泡鱼
摘要

目录简介1. 继承 Qthread 重写 run 函数2. 继承 QObject 调用 moveToThread3. 继承 QRunnable 重新 run 函数,结合 QThrea

简介

开发过程中,使用线程是经常会遇到的场景,本篇文章就来整理一下 Qt 中使用线程的五种方式,方便后期回顾。前面两种比较简单,一笔带过了,主要介绍后面三种。最后两种方法博主最喜欢,不需要继承类,可以直接把需要执行的函数放到线程中去运行

1. 继承 QThread 重写 run 函数


class Thread : public QThread
{
    Q_OBJECT
public:
	virtual void run() override;
}

void Thread::run()
{
	...
}
  • 可调用 thread.start()启动线程,会自动调用 run 函数
  • 可调用 thread.isRunning()判断线程是否已启动
  • 可调用 thread.terminate()终止线程
  • 可调用 thread.wait()等待线程终止

2. 继承 QObject 调用 moveToThread


class Test : public QObject
{
    Q_OBJECT
public:
    void test();
}

QThread th;
Test test;
test.moveToThread(&th);

需要注意的是:此方法与继承 QThread 相比较,继承 QThread 只有 run 函数中的操作是在线程中执行的,而此方法中所有的成员函数都是在线程中执行

3. 继承 QRunnable 重新 run 函数,结合 QThreadPool 实现线程池


#include <QObject>
#include <QRunnable>
#include <QThread>
#include <QThreadPool>
#include <QDebug>

class BPrint : public QRunnable
{
	void run()
	{
	    for ( int count = 0; count < 5; ++count )
	    {
			qDebug() << QThread::currentThread();
			QThread::msleep(1000);
	    }
	}
};

int main(int arGC, char *argv[])
{
	QCoreApplication a(argc, argv);
 
	QThreadPool threadpool;	           		// 构建一个本地的线程池
	threadpool.setMaxThreadCount(3);        // 线程池中最大的线程数
	
    for ( int num = 0; num < 100; ++num )
	{
	    BPrint *print;    					// 循环构建可在线程池中运行的任务
	    threadpool.start(print);      		// 线程池分配一个线程运行该任务
	    QThread::msleep(1000);
	}
	
	return a.exec();
}

在上述例子当中,我们创建的 QRunnable 类型的指针 BPrint *print 是不需要我们手动去回收内存的,QThreadPool 在结束该任务的执行后会将对该内存进行清空

有的小伙伴会有疑问,既然有 QThread 线程类了,为啥还要用 QRunnable + QThreadPool 创建线程池的方法来使用线程机制呢,感觉用起来很麻烦啊。所以这里要说明一下此方法的使用场景,当线程任务量非常大的时候,如果频繁的创建和释放 QThread 会带来非常大的内存开销,而线程池则可以有效避免这个问题

还有一个问题需要注意一下,QThread 是集成自 QObject 的,我们通常会使用信号槽与外界进行通信。而 QRunnable 并不是继承自 QObject 类的,所以他无法使用信号槽机制进行通信。这里推荐两种方法,一个是使用 QMetaObject::invokeMethod()函数。另一个是使用多重继承的方法,自定义类需要同时继承自 QRunnable 和 QObject

4. 使用 C++ 11 中的 sth::thread


#include <thread>
void threadfun1()
{
    std::cout << "threadfun1 - 1\r\n" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "threadfun1 - 2" << std::endl;
}

void threadfun2(int iParam, std::string sParam)
{
    std::cout << "threadfun2 - 1" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(5));
    std::cout << "threadfun2 - 2" << std::endl;
}

int main()
{
    std::thread t1(threadfun1);
    std::thread t2(threadfun2, 10, "abc");
    t1.join();		// 等待线程 t1 执行完毕
    std::cout << "join" << std::endl;
    t2.detach();	// 将线程 t2 与主线程分离
    std::cout << "detach" << std::endl;
}

运行结果:
threadfun1 - 1
threadfun2 - 1

threadfun1 - 2
join
detach

根据输出结果可以得知,t1.join() 会等待t1线程退出后才继续往下执行,t2.detach() 并不会等待,detach字符输出后,主函数退出,threadfun2还未执行完成,但是在主线程退出后,t2的线程也被已经被强退出

5. Qt QtConcurrent 之 Run 函数

Concurrent 是并发的意思,QtConcurrent 是一个命名空间,提供了一些高级的 api,使得所写的程序可根据计算机的 CPU 核数,自动调整运行的线程数目。这意味着今后编写的应用程序将在未来部署在多核系统上时继续扩展

函数原型如下:
QFuture<T> QtConcurrent::run(Function function, ...)
QFuture<T> QtConcurrent::run(QThreadPool *pool, Function function, ...)

简单来说,QtConcurrent::run() 函数会在一个单独的线程中执行,并且该线程取自全局 QThreadPool,该函数的返回值通过 QFuture API 提供

需要注意的是:
1)该函数可能不会立即运行; 函数只有在线程可用时才会运行
2)通过 QtConcurrent::run() 返回的 QFuture 不支持取消、暂停,返回的 QFuture 只能用于查询函数的运行/完成状态和返回值
3) Qt Concurrent 已经从 QtCore 中移除并成为了一个独立的模块,所以想要使用 QtConcurrent 需要在 pro 文件中导入模块:
QT += concurrent

使用方式有以下几种:
1)将函数运行在某一个线程中,需要使用 extern


extern void func();
QFuture<void> future = QtConcurrent::run(func);

2)向该函数传递参数


extern void FuncWithArguments(int arg1, const QString &string);

int integer = ...;
QString string = ...;
// 需要传递的参数,则跟在函数名之后,依次加入
QFuture<void> future = QtConcurrent::run(FuncWithArguments, integer, string);

3) 获取该函数的计算结果


extern QString Func(const QByteArray &input);

QByteArray byte_array = ...;
QFuture<QString> future = QtConcurrent::run(func, byte_array);
...
QString result = future.result();

4)常量成员函数


QByteArray bytearray = "hello world";
// 在一个单独的线程中,调用 QByteArray 的常量成员函数 split(),传递给 run() 函数的参数是 bytearray
QFuture< QList<QByteArray> > future = QtConcurrent::run(bytearray, &QByteArray::split, ',');
...
QList<QByteArray> result = future.result();

5)非常量成员函数


QImage image = ...;
// 在一个单独的线程中,调用 QImage 的非常量成员函数 invertPixels(),传递给 run() 函数的参数是 &image
QFuture<void> future = QtConcurrent::run(&image, &QImage::invertPixels, QImage::InvertRgba);
...
future.waitForFinished();

6)Lambda 表达式


#include <QFuture>
#include <QtConcurrent>
#include <QThreadPool>

QThreadPool pool;
QFuture<void> future = QtConcurrent::run(&pool, [&](QObject *receiver){
    cv::Mat mat = QYImageProcessing::convertQImageToMat(image);
    cv::Mat center = cv::imread("dynaPhase_center.png");
    
    dynaPhase_alive = QYImageProcessing::getDiffPoint(mat, center);
    
    // 根据三个点自适应模拟条纹
    cv::Mat ret = DynamicCarrier::DC_Adaptive_Simulation(dynaPhase_center, dynaPhase_alive, dynaPhase_align);
    ret = ret*255;
    ret.convertTo(ret, CV_8UC1);
    QImage adaptive = QYImageProcessing::convertMatToQImage(ret);
    
    QYAlignControl *align = static_cast<QYAlignControl *>(receiver);
    align->callQmlGetAlivePoint(adaptive, dynaPhase_alive.x, dynaPhase_alive.y);
}, this);

到此这篇关于Qt 中开启线程的五种方式的文章就介绍到这了,更多相关Qt 线程内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Qt 中开启线程的多种方式小结

本文链接: https://www.lsjlt.com/news/134390.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Qt 中开启线程的多种方式小结
    目录简介1. 继承 QThread 重写 run 函数2. 继承 QObject 调用 moveToThread3. 继承 QRunnable 重新 run 函数,结合 QThrea...
    99+
    2024-04-02
  • qt怎么开启多个线程
    在Qt中,可以使用QThread类来开启多个线程。下面是一个简单的示例代码:```cpp#include #include clas...
    99+
    2023-09-22
    qt
  • java多线程开启的三种方式你知道吗
    目录1、继承Thread类,新建一个当前类对象,并且运行其start()方法2、实现Runnable接口,然后新建当前类对象,接着新建Thread对象时把当前类对象传进去,最后运行T...
    99+
    2024-04-02
  • Java线程协作的两种方式小结
    目录为什么线程之间需要协作介绍方法一方法二为什么线程之间需要协作 线程之间相互配合,完成某项工作,比如:一个线程修改了一个对象的值,而另一个线程感知到了变化,然后进行相应的操作,整个...
    99+
    2023-05-19
    Java线程协作
  • QT实现多线程两种方式案例详解
    Qt线程 Qt4.7之前版本处理步骤 1.自定义一个类,继承于QThread。 class MyThread:public QThread{ public: vid ru...
    99+
    2024-04-02
  • springboot创建线程池的两种方式小结
    目录springboot创建线程池两种方式1.使用static代码块创建2.使用@Configuration @bean注解,程序启动时创建springboot如何开启线程池定义线程...
    99+
    2024-04-02
  • Java开启多线程常见的4种方法
    目录简介1. 实现 Runnable 接口2. 实现 Callable 接口3. 继承 Thread 类4. 匿名内部类的写法简介 常见的4种使用线程的方法: 1实现 Runnabl...
    99+
    2024-04-02
  • Java 开启多线程常见的4种方法
    Java 开启多线程常见的4种方法如下:1. 继承 Thread 类:创建一个继承自 Thread 类的子类,并重写 run() 方...
    99+
    2023-08-14
    Java
  • java实现/创建线程的几种方式小结
    进程与线程 进程可以简单理解成一个可执行程序例如.exe,在Windows中的任务管理器中可以查看每一个进程,进程是一次程序的执行,是程序在数据集合上运行的过程,是系统资源调度的一...
    99+
    2024-04-02
  • java 实现开启异步线程的几种方式
    在Java中,有多种方式可以实现异步线程以避免在主线程中执行耗时操作导致界面卡顿的问题。以下是几种常用的方式: 使用Thread类:可以使用Thread类来创建一个新的线程,并在其run()方法中执行耗时操作。例如: new Thread(...
    99+
    2023-08-17
    java
  • Java详解实现多线程的四种方式总结
    目录前言一、四种方式实现多线程1.继承Thread类创建线程2.实现Runnable接口创建线程3.实现Callable接口4.实现有返回结果的线程二、多线程相关知识1.Runnab...
    99+
    2024-04-02
  • python - 线程的启动的几种方式
    本文主要给大家介绍python启动线程的四种方式 1. 使用 threading 模块 创建 Thread 对象,然后调用 start() 方法启动线程。 import threadingdef fu...
    99+
    2023-10-21
    python 开发语言
  • C#多态的三种实现方式(小结)
    C#实现多态主要有3种方法,虚方法,抽象类,接口 1 虚方法 在父类的方法前面加关键字virtual, 子类重写该方法时在方法名前面加上override关键字,例如下面的Perso...
    99+
    2024-04-02
  • 多线程同步的四种方式
    1. 互斥锁(Mutex):使用互斥锁可以保证在同一时间只有一个线程可以访问共享资源。当一个线程获得了互斥锁,其他线程就需要等待该线...
    99+
    2023-09-07
    多线程
  • Windows7系统下开启无线的多种方法
      适用范围:   WIN7 无线 开启   知识点分析:   Windows 7系统下无线开启的方法。   操作步骤:   1. 按WIN+X,我们需要打开移动中心,先看一下无线的状态,如图:   第一种是关闭状态,...
    99+
    2023-06-06
    Win7 无线 Windows7 系统 方法
  • pythontornado开启多进程的几种方法
    目录1. 使用多个进程启动多个Tornado实例2. 使用tornado.process.fork_processes()方法启动多个进程3.使用标准库中的multiprocessi...
    99+
    2023-05-16
    python tornado多进程 tornado多进程
  • C# 使用多线程的几种方式
    在C#中,有几种方式可以使用多线程:1. 使用Thread类:可以创建一个新线程并在其中执行指定的方法。可以使用Thread类来启动...
    99+
    2023-09-15
    C#
  • java创建多线程的七种方式
    一、继承Thread,重写run方法 通过自定义一个类(这里起名为:MyThread),继承Thread类,重写run方法,最后在main方法中new出MyThread实例,调用这个实例的继承的Thread类的start方法创建一个线程。 ...
    99+
    2023-09-26
    java
  • Java线程创建的四种方式总结
    多线程的创建,方式一:继承于Thread类 1.创建一个继承于Thread类的子类 2.重写Thread类的run()--->将此线程执行的操作声明在run()中 3.创建Th...
    99+
    2024-04-02
  • Java多线程中Lock的使用小结
    Jdk1.5 以后,在 java.util.concurrent.locks 包下,有一组实现线程同步的接口和类,说到线程的同步,可能大家都会想到 synchronized 关键字,...
    99+
    2023-05-18
    Java多线程Lock Java Lock
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作