Qt-自定义线程池(一)

简介

在做一个项目时,总会有许多的耗时操作,例如数据处理、数据库增删改查、文件读写、外部程序加载等等,有时甚至这些操作会同时发生,这个时候就需要创建一个线程池来把这些操作维护起来。

实现思路

要实现自定义的线程池首先要重写QRunnable类中的run()函数,耗时操作都放在run当中执行。因为不同的情况下run()函数的实现存在较大的差异,就以数据库操作来说,一个表的不同查询条件都会使run()函数后不同的实现,而我们又不能每一种操作都写一个自定义的QRunnable类,所以我们需要给自定义的QRunnable类定义一个私有成员:函数指针。用户根据需要实现这个函数,run()函数中来执行这个函数指针,这样就可以实现同一类对象的不同实现。

private:
	bool(*pf)();

线程执行完之后呢?

有时候我们需要知道线程什么时候执行结束,执行是否成功,来进行后续的操作。举一个简单的例子,将数据库的插入操作放入线程中,在线程结束后我们需要刷新当前显示的表格内容,再好一点我们可以弹出一个提示框来提醒用户插入成功或失败,那么这个操作如何来完成?

在线程结束的时候我们需要发送一个信号,来说明线程的执行情况

protected:
	void run()
	{
		bool flag = (*pf)();
		emit SendRunableSignal(flag);
		return;
	}

signals:
	void SendRunableSignal(bool);

如上代码所述,线程是否执行成功,也需要通过这个函数指针来进行判断,所以该函数指针的返回值类型为bool。有信号就需要绑定相应的槽函数,如上述函数指针,槽函数也需要用户来实现,绑定方式如下:

    ExperimentRunable *runable = new ExperimentRunable();
	connect(runable, &ExperimentRunable::SendRunableSignal, this, signal_pf);     //signal_pf为槽函数函数指针

这样就基本实现自定义线程,接下来只需要把不同的自定义线程添加到线程池执行即可。

代码实现

  • custom_thread_pool_service.h
    ExperimentThread类为自定义线程例子,可根据需要查看
    #pragma once
#pragma once
#include <QObject>
#include <QThreadPool>
#include <QThread>
#include <QRunnable>
#include <QDebug>
#include "custom_thread_pool_global.h"
/*****************************************************************/
class ExperimentThread
	: public QThread
{
	Q_OBJECT

public:
	void SetFunction(void(*_pf)()){
		pf = _pf;
	}
protected:
	void run()
	{
		(*pf)();
		emit SendAlgorithms();
		return;
	}
signals:
	void SendAlgorithms();
private:
	void(*pf)();
};
/*****************************************************************/
class ExperimentRunable
	: public QObject
	, public QRunnable
{
	Q_OBJECT
public:
	explicit ExperimentRunable(QObject *parent = nullptr)
	{

	}
	~ExperimentRunable()
	{
	}
	void SetFunction(bool(*_pf)()){
		pf = _pf;
	}
protected:
	void run()
	{
		bool flag = (*pf)();
		emit SendRunableSignal(flag);
		return;
	}
signals:
	void SendRunableSignal(bool);
private:
	bool(*pf)();
};
/*****************************************************************/
class CustomThreadPoolService
	:public QObject
	,public ICustomThreadPool
{
	Q_OBJECT
public:
	CustomThreadPoolService();
	~CustomThreadPoolService();

	virtual void CreatThread(bool(*_pf)(), void(*signal_pf)(bool));

private:
	//线程池对象
	QThreadPool *thread_pool_;

};
  • custom_thread_pool_service.cpp
#include "custom_thread_pool_service.h"


CustomThreadPoolService::CustomThreadPoolService()
{
	thread_pool_ = new QThreadPool();
    //设置线程池最大容量
	thread_pool_->globalInstance()->setMaxThreadCount(20);
}


CustomThreadPoolService::~CustomThreadPoolService()
{
}

void CustomThreadPoolService::CreatThread(bool(*_pf)(), void(*signal_pf)(bool))
{
	ExperimentRunable *runable = new ExperimentRunable();
	connect(runable, &ExperimentRunable::SendRunableSignal, this, signal_pf);
	runable->SetFunction(_pf);
	runable->setAutoDelete(true);
	thread_pool_->start(runable);
}

存在问题

这个自定义线程池存在一个很大的问题,就是上述两个函数指针需要被定义为全局函数,因为无法确定传入对象类型(举个例子,可能一个界面是数据库界面,另一个界面是数据解析界面,两个界面两个类,无法定义传入函数所属对象的类型,所以需要定义为全局函数),所以该函数指针不可以是某一类对象成员函数,但是这样的话函数中用到的变量就都必须定义为静态全局变量,用起来终归是不太方便。目前想到的是给这个线程池对象定义一个公共的父类,所以使用到线程池的都继承这个父类,这样传入的对象类型就可以确认为父类对象,具体实现后再更新。

以上是对自定义线程池的一点理解,如果此文帮助到你( •̀ ω •́ )✧,动动小手点个赞可好O(∩_∩)O。
原创文章,转载请标明本文出处。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

梦醒梦起

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

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

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

打赏作者

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

抵扣说明:

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

余额充值