看本博客之前,可以先看看我这篇多线程博客:qt多线程使用方式_我是标同学的博客
为了实现方便使用的线程管理类,类似于QtConcurrent::run()函数,就很好用,而且还能直接给相应的实参。但是该方式不能随时停止线程,满足不了我们的使用,但是其思想还是可以借鉴的。
这里为了实现我们自己的方便的线程管理类,首先需要了解c++中模板函数的使用,可以看我这篇博客:c++模板的原理与使用_我是标同学的博客
使用方式:
接下来,是我们的线程管理类,功能是通过给定一个线程名字(作为唯一的标识符),待执行函数,函数的实参(可以多个),然后就能自动创建出该线程,而且可以进行停止等操作。使用如下(是不是很方便就使用啦,哈哈哈,不用去子类化QThread,重写run函数,等繁琐步骤了,此外qt自带的几个线程类都不太好用,而std标准库中的线程类就不错,可以直接给实参,但是使用起来还是不如qt库那么顺手好用,所以我才自己去写这个qt风格的线程库的):
//创建4个线程,分别给入不同的执行函数,以及实参,都能正确运行起来
mTm->executeThread("xx", this, &MainWindow::print);
mTm->executeThread("xx1", this, &MainWindow::print1, 9);
mTm->executeThread("xx2", this, &MainWindow::print2, QString("nihao"));
mTm->executeThread("xx3", this, &MainWindow::print3, 5, QString("yaya"));
//停止指定的线程
mTm->stopThread("xx");
mTm->stopThread("xx1");
主要的工程代码(简单建立个工程就能运行了),如下:
1. mainwindow.cpp文件
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "thread/threadmanager.h"
#include "thread/thread.h"
#include <QTabBar>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
mTm = new ThreadManager(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::print()
{
for (int i = 0; i < 10000; ++i) {
int j = 100000000;
while (j--) {
i = i;
}
qDebug()<<i;
}
}
void MainWindow::print1(int a)
{
for (int i = 0; i < 10000; ++i) {
int j = 100000000;
while (j--) {
i = i;
}
qDebug()<<a;
}
}
void MainWindow::print2(QString str)
{
for (int i = 0; i < 10000; ++i) {
int j = 100000000;
while (j--) {
i = i;
}
qDebug()<<str;
}
}
void MainWindow::print3(int a, QString str)
{
for (int i = 0; i < 10000; ++i) {
int j = 100000000;
while (j--) {
i = i;
}
qDebug()<<a<<str;
}
}
#include<iostream>
using namespace std;
#include<string>
void MainWindow::on_pushButton_clicked()
{
// mTm->test(2);
mTm->executeThread("xx", this, &MainWindow::print);
mTm->executeThread("xx1", this, &MainWindow::print1, 9);
mTm->executeThread("xx2", this, &MainWindow::print2, QString("nihao"));
mTm->executeThread("xx3", this, &MainWindow::print3, 5, QString("yaya"));
}
void MainWindow::on_pushButton_2_clicked()
{
mTm->stopThread("xx");
mTm->stopThread("xx1");
}
2. mainwindow.h文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class ThreadManager;
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void print();
void print1(int a);
void print2(QString str);
void print3(int a, QString str);
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::MainWindow *ui;
ThreadManager* mTm;
};
#endif // MAINWINDOW_H
3. thread.h文件
(注意:不需要thread.cpp文件,因为该类是模板类,类的声明和定义都在一个.h文件里了,这是模板类必须要求的,否则编译报错,可以看我前面引用的文章)
#ifndef THREAD_H
#define THREAD_H
#include <QThread>
#include <QObject>
#include <QList>
//#include "threadmanager.h"
//模板类 或者 函数 声明和实现必须放在同一个头文件里
//
//写模板函数时,头文件和cpp文件不能分离,就是说你头文件里有模板的函数必须在头文件里实现,没有模板的函数可以放到cpp文件实现,模板类也如此
//
//用class或者typename都可以,一样的作用
template <class Return, class Class>
class Thread0 : public QThread
{
public:
explicit Thread0(QObject *parent = nullptr): QThread{parent}
{
}
// explicit Thread(const Class *object, T (Class::*fn)(), QObject *parent = nullptr);
explicit Thread0(Class *object, Return (Class::*fn)(), QObject *parent = nullptr): QThread{parent}
{
mObject = object;
mFun = fn;
}
protected:
void run()
{
//全部在这里处理子线程的复杂业务
(mObject->*mFun)();
}
private:
// FunForThread mFunExe;
//要想用模板定义成员变量,那么只能是整个类定义为模板类
Class* mObject;
Return (Class::*mFun)();
int mNumberArgs = 0;
};
template <class Return, class Class, class Arg1>
class Thread1 : public QThread
{
public:
explicit Thread1(QObject *parent = nullptr): QThread{parent}
{
}
// explicit Thread(const Class *object, T (Class::*fn)(), QObject *parent = nullptr);
explicit Thread1(Class *object, Return (Class::*fn)(Arg1 arg1), Arg1 arg1, QObject *parent = nullptr): QThread{parent}
{
mObject = object;
mFun = fn;
mArg1 = arg1;
}
protected:
void run()
{
//全部在这里处理子线程的复杂业务
(mObject->*mFun)(mArg1);
}
private:
// FunForThread mFunExe;
//要想用模板定义成员变量,那么只能是整个类定义为模板类
Class* mObject;
Return (Class::*mFun)(Arg1 arg1);
Arg1 mArg1;
};
template <class Return, class Class, class Arg1, class Arg2>
class Thread2 : public QThread
{
public:
explicit Thread2(QObject *parent = nullptr): QThread{parent}
{
}
// explicit Thread(const Class *object, T (Class::*fn)(), QObject *parent = nullptr);
explicit Thread2(Class *object, Return (Class::*fn)(Arg1 arg1, Arg2 arg2), Arg1 arg1, Arg2 arg2, QObject *parent = nullptr): QThread{parent}
{
mObject = object;
mFun = fn;
mArg1 = arg1;
mArg2 = arg2;
}
protected:
void run()
{
//全部在这里处理子线程的复杂业务
(mObject->*mFun)(mArg1, mArg2);
}
private:
// FunForThread mFunExe;
//要想用模板定义成员变量,那么只能是整个类定义为模板类
Class* mObject;
Return (Class::*mFun)(Arg1 arg1, Arg2 arg2);
Arg1 mArg1;
Arg2 mArg2;
};
template <class Return, class Class, class Arg1, class Arg2, class Arg3>
class Thread3 : public QThread
{
public:
explicit Thread3(QObject *parent = nullptr): QThread{parent}
{
}
// explicit Thread(const Class *object, T (Class::*fn)(), QObject *parent = nullptr);
explicit Thread3(Class *object, Return (Class::*fn)(Arg1 arg1, Arg2 arg2, Arg3 arg3), Arg1 arg1, Arg2 arg2, Arg3 arg3, QObject *parent = nullptr): QThread{parent}
{
mObject = object;
mFun = fn;
mArg1 = arg1;
mArg2 = arg2;
mArg3 = arg3;
}
protected:
void run()
{
//全部在这里处理子线程的复杂业务
(mObject->*mFun)(mArg1,mArg2,mArg3);
}
private:
// FunForThread mFunExe;
//要想用模板定义成员变量,那么只能是整个类定义为模板类
Class* mObject;
Return (Class::*mFun)(Arg1 arg1,Arg2 arg2,Arg3 arg3);
Arg1 mArg1;
Arg2 mArg2;
Arg3 mArg3;
};
template <class Return, class Class, class Arg1, class Arg2, class Arg3, class Arg4>
class Thread4 : public QThread
{
public:
explicit Thread4(QObject *parent = nullptr): QThread{parent}
{
}
// explicit Thread(const Class *object, T (Class::*fn)(), QObject *parent = nullptr);
explicit Thread4(Class *object, Return (Class::*fn)(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4), Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg3 arg4, QObject *parent = nullptr): QThread{parent}
{
mObject = object;
mFun = fn;
mArg1 = arg1;
mArg2 = arg2;
mArg3 = arg3;
mArg4 = arg4;
}
protected:
void run()
{
//全部在这里处理子线程的复杂业务
(mObject->*mFun)(mArg1,mArg2,mArg3,mArg4);
}
private:
// FunForThread mFunExe;
//要想用模板定义成员变量,那么只能是整个类定义为模板类
Class* mObject;
Return (Class::*mFun)(Arg1 arg1,Arg2 arg2,Arg3 arg3,Arg4 arg4);
Arg1 mArg1;
Arg2 mArg2;
Arg3 mArg3;
Arg4 mArg4;
};
#endif // THREAD_H
4. threadmanager.cpp文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class ThreadManager;
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void print();
void print1(int a);
void print2(QString str);
void print3(int a, QString str);
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::MainWindow *ui;
ThreadManager* mTm;
};
#endif // MAINWINDOW_H
5. threadmanager.h文件
#ifndef THREADMANAGER_H
#define THREADMANAGER_H
#if 1
#include <QObject>
#include <QHash>
#include <QVariant>
#include <QDebug>
#include "thread.h"
class MainWindow;
class ThreadManager : public QObject
{
Q_OBJECT
public:
explicit ThreadManager(QObject *parent = nullptr);
bool stopThread(QString name);
#if 1
//这个用于去创建线程
// void executeThread(QString name, FunForThread funExe, QList<QVariant> args);
//难度不能成员函数模板???只能全局函数模板或者类模板???
//模板有3种形式:模板全局函数,模板类内成员函数,模板整个类(里面的成员变量和函数都可以是模板化了)
//模板类 或者 函数 声明和实现必须放在同一个头文件里
template <class Return, class Class>
void executeThread(QString name, Class *object, Return (Class::*fn)())
{
Thread0<Return, Class>* t = new Thread0<Return, Class>(object, fn, this);
if(mThreads.contains(name))
stopThread(name);
mThreads.insert(name, t);
// list.append((int)t);
qDebug()<<this;
// list.append(t);
qDebug()<<t;
t->start();
}
template <class Return, class Class, typename Arg1>
void executeThread(QString name, Class *object, Return (Class::*fn)(Arg1 arg1), Arg1 arg1)
{
Thread1<Return, Class, Arg1>* t = new Thread1<Return, Class, Arg1>(object, fn, arg1, this);
if(mThreads.contains(name))
stopThread(name);
mThreads.insert(name, t);
t->start();
}
template <class Return, class Class, typename Arg1, typename Arg2>
void executeThread(QString name, Class *object, Return (Class::*fn)(Arg1 arg1, Arg2 arg2), Arg1 arg1, Arg2 arg2)
{
Thread2<Return, Class, Arg1, Arg2>* t = new Thread2<Return, Class, Arg1, Arg2>(object, fn, arg1, arg2, this);
if(mThreads.contains(name))
stopThread(name);
mThreads.insert(name, t);
t->start();
}
template <class Return, class Class, typename Arg1, typename Arg2, typename Arg3>
void executeThread(QString name, Class *object, Return (Class::*fn)(Arg1 arg1, Arg2 arg2, Arg3 arg3), Arg1 arg1, Arg2 arg2, Arg3 arg3)
{
Thread3<Return, Class, Arg1, Arg2, Arg3>* t = new Thread3<Return, Class, Arg1, Arg2, Arg3>(object, fn, arg1, arg2, arg3, this);
if(mThreads.contains(name))
stopThread(name);
mThreads.insert(name, t);
t->start();
}
template <class Return, class Class, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
void executeThread(QString name, Class *object, Return (Class::*fn)(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4), Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
{
Thread4<Return, Class, Arg1, Arg2, Arg3, Arg4>* t = new Thread4<Return, Class, Arg1, Arg2, Arg3, Arg4>(object, fn, arg1, arg2, arg3, arg4, this);
if(mThreads.contains(name))
stopThread(name);
mThreads.insert(name, t);
t->start();
}
#endif
private:
// template <class Return, class Class> 成员变量不能单独设为模板变量
QHash<QString, QThread*> mThreads;
};
#endif
#endif // THREADMANAGER_H