QThread之重写run() 实现线程与业务解耦

一、线程的一般实现形式

Qt中线程类QThread有2种使用方式。

1.继承自QThread,重写run()

 class MyThread : public QThread
 {
     Q_OBJECT
 protected:
     virtual void run() override { ... }
 };

我们一般在run()中加个死循环,不停处理业务或者调用相关的方法。这样的话,我们的业务逻辑与线程紧密耦合在一起。

适用场景:

用于一直不停处理业务,而不是处理完一单业务后,就可以休眠的这种场景。

2.moveToThread

使用一个QObject作为Worker,并moveToThread到线程上。

此种方式不在本文讨论范围内,故不赘述。

二、抽象业务逻辑

我们的业务是需要挂在线程上跑的,那么业务应该有个可执行接口,以实现挂接到线程上。那简单,来一个接口。

IRunable.h

class IRunable
{
public:
    virtual ~IRunable() {}
    virtual void exec() = 0;
};

业务,我们也叫它任务,定义2个任务。

class Task1 : public IRunable
{
public:
    virtual void exec() override
    {
        qDebug() << "do Task1...";
    }
};

class Task2 : public IRunable
{
public:
    virtual void exec() override
    {
        qDebug() << "do Task2...";
    }
};

我们这里使用的线程类是Thread,它派生于QThread,只不过重写的是Thread::process(),与使用QThread无异。

我们自定义Executor执行器类,继承自Thread,原理是通过addRunable(IRunable *able)添加可执行对象到QList里面,然后在线程执行函数process()中,依次执行list中的对象。

Executor.cpp

Executor::Executor(QObject *parent)
    : Thread(parent)
{

}

Executor::~Executor()
{
    Thread::stop();
}

void Executor::addRunable(IRunable *able)
{
    runableList.append(able);
}

void Executor::addRunables(const QList<IRunable *> &ables)
{
    runableList.append(ables);
}

QList<IRunable *> Executor::getRunables()
{
    return runableList;
}

void Executor::process()
{
    foreach (auto able, runableList)
    {
        able->exec();
    }
}

代码比较简单,这样做,可以让任务与线程之间依赖于接口,而不依赖于实现,实现线程与业务逻辑解耦。此后对任务的扩展,不牵涉到线程,且可以实现单线程-多任务,多线程-多任务的灵活配置。

另外,多线程对于共享数据的竞争保护,也可以在各自的任务实现类中,进行处理。

三、测试

mainwindow.cpp

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    executor = new Executor();

    runableList.append(new Task1());
    runableList.append(new Task2());
    executor->addRunables(runableList);
}

MainWindow::~MainWindow()
{
    delete executor;
    executor = nullptr;
    qDeleteAll(runableList);
    runableList.clear();
    delete ui;
}

void MainWindow::on_pushButton_start_clicked()
{
    executor->start();
}

void MainWindow::on_pushButton_pause_clicked()
{
    executor->pause();
}

void MainWindow::on_pushButton_stop_clicked()
{
    executor->stop();
}

void MainWindow::on_pushButton_resume_clicked()
{
    executor->resume();
}

void MainWindow::on_pushButton_clicked()
{
    Thread::State s = executor->state();
    if (s == Thread::Stoped)
    {
        qDebug() << "state : Stoped";
    }
    else if (s == Thread::Running)
    {
        qDebug() << "state : Running";
    }
    else if (s == Thread::Paused)
    {
        qDebug() << "state : Paused";
    }
}

运行效果:
QThread之重写run() 实现线程与业务解耦_第1张图片

代码地址:

https://gitee.com/bailiyang/cdemo/tree/master/Qt/37PauseQThread/PauseQThread


===================================================

===================================================

业余时间不定期更新一些想法、思考文章,欢迎关注,共同探讨,沉淀技术!

            QThread之重写run() 实现线程与业务解耦_第2张图片

你可能感兴趣的:(QT,QThread)