QT线程之“旁门左道”之二:多个QRunable运行结束检测

8 篇文章 0 订阅

上一篇文章中提到在QT中使用线程类QThread,但是QT中还有一个同样可以实现多线程那就是QRunable,这个QT提供的轻量级的线程处理机制,关于QRunable的使用可以详见我这篇文章Qt 线程池的使用以及和主线程的消息同步

QRunable可以通过线程池来控制,QThreadPool线程池是一个全局的单例模式,使用也是比较方便的,但是如何检测同时运行的QRunable线程结束了呢?有的同学会说可以使用waitForDone线程池提供的函数来实现:

waitForDone

Waits up to msecs milliseconds for all threads to exit and removes all threads from the thread pool. Returns true if all threads were removed; otherwise it returns false. If msecs is -1 (the default), the timeout is ignored (waits for the last thread to exit). 

自定义一个QRunnable的子类

#pragma once

#include <QRunnable>
#include "ILoadData.h"

class QtLoadRunable : public QRunnable {

public:
	QtLoadRunable(ILoadData *load);
	~QtLoadRunable();

	virtual void run();
private:
	ILoadData* _loadData = nullptr;
};

#include "QtLoadRunable.h"

QtLoadRunable::QtLoadRunable(ILoadData *load){
	_loadData = load;
}

QtLoadRunable::~QtLoadRunable() {
}

void QtLoadRunable::run() {
	_loadData->loadData();
}

继续使用上一篇文章中的ILoadData接口,然后定义一个界面类,使其继承这个接口类,并且实现这个接口函数:

void MyThread::loadData() {
	while (true) {
		QThread::msleep(1000);
		count++;
		qDebug() << QStringLiteral("线程运行中...... ")<< count;
	}
}

然后启动这个线程调用接口:

void MyThread::slotThread() {

	QtLoadRunable* runnable = new QtLoadRunable(this);
	QThreadPool::globalInstance()->start(runnable);

	QThreadPool::globalInstance()->waitForDone();

	qDebug() << QStringLiteral("线程运行完成!");
}

然后运行程序,不断的打印出信息,但是界面不在接受任何鼠标或者键盘的操作,程序就卡住了,出现了假死:
在这里插入图片描述

调用waitForDone这个函数会阻塞主线程的,使整个程序处于“假死”的状态,那么如何检测到所有的线程运行完成,又不会阻塞主线程呢?

可以定义一个线程计数器,初始化会记录开启的线程数,每当一个线程运行完成的后,计数器就会加1,当计数器的数量等于初始化的数量时,表示所有的线程已经运行完成了。

首先定义三个加载数据的类,分别继承加载接口:

第一个:

#pragma once
#include "ILoadData.h"
class LoadData1 :public ILoadData {
public:
	LoadData1();
	~LoadData1();
	virtual void loadData()override;
};
#include "LoadData1.h"
#include <QThread>
LoadData1::LoadData1() {
}

LoadData1::~LoadData1() {
}

void LoadData1::loadData() {
	QThread::msleep(1000);
}

第二个:

#pragma once
#include "ILoadData.h"
class LoadData2 :public ILoadData {
public:
	LoadData2();
	~LoadData2();
	virtual void loadData()override;
};
#include "LoadData2.h"
#include <QThread>

LoadData2::LoadData2() {
}

LoadData2::~LoadData2() {
}

void LoadData2::loadData() {
	QThread::msleep(2000);
}

第三个:

#pragma once
#include "ILoadData.h"
class LoadData3 :public ILoadData {
public:
	LoadData3();
	~LoadData3();

	virtual void loadData()override;

};

#include "LoadData3.h"
#include <QThread>

LoadData3::LoadData3() {
}

LoadData3::~LoadData3() {
}

void LoadData3::loadData() {
	QThread::msleep(3000);
}

定义线程计数器管理类,为了方便使用,这个类使用单例模式:

#pragma once
#include <QMutex>

#define RunCntInst() (RunCount::getInstance())

class RunCount {
private:
	RunCount();
	static RunCount* _instance;
public:
	~RunCount();
	static RunCount* getInstance();

	//设置运行的总线程数
	void totalRunable(int total);

	//每次运行完成就调用这个函数,使线程计数器+1
	void finished();
private:
	int _totalRunable = 0;//总共启动的线程数
	int _finishedRunable = 0;//已经运行完成的线程数

	QMutex mutex;//线程锁
};

#include "RunCount.h"
#include <QDebug>

RunCount* RunCount::_instance = new RunCount;

RunCount::RunCount() {
}

RunCount::~RunCount() {
}

RunCount* RunCount::getInstance() {
	return _instance;
}

void RunCount::totalRunable(int total) {
	_totalRunable = total;
}

void RunCount::finished() {
	mutex.lock();//加锁锁定,防止多个线程同时使用这部分
	_finishedRunable++;
	if (_finishedRunable == _totalRunable){

		qDebug() << QStringLiteral("线程运行完成!");
	}
	mutex.unlock();
}

调用:

void MyThread::slotThread() {
	RunCntInst()->totalRunable(3);
	
	LoadData1* load1 = new LoadData1;
	QtLoadRunable* runnable1 = new QtLoadRunable(load1);
	QThreadPool::globalInstance()->start(runnable1);

	LoadData2* load2 = new LoadData2;
	QtLoadRunable* runnable2 = new QtLoadRunable(load2);
	QThreadPool::globalInstance()->start(runnable2);

	LoadData3* load3 = new LoadData3;
	QtLoadRunable* runnable3 = new QtLoadRunable(load3);
	QThreadPool::globalInstance()->start(runnable3);
}

运行结果:
在这里插入图片描述

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wb175208

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值