Qt多线程1

171 阅读2分钟

Qt的多线程对于设计并行程序来说很有帮助,但是多线程因为其固有的一些特性,会导致程序会出现各种隐患,尤其是类设计不好的时候尤为严重。

这里我们将详细介绍一下Qt的多线程技术,包括如何制作一个线程安全的类。

首先我们先写一个简单的例子:

首先,我们再次使用一个类DebugText ,该类继承自DebugWidget类:

`#pragma once
#ifndef _DEBUGWIDGET_H__
#define _DEBUGWIDGET_H__
#include <QWidget>
#include <qtextedit.h>
#include <qlayout.h>
#include <QPainter>
class DebugWidget : public QWidget {
        Q_OBJECT

public:

        ~DebugWidget();


protected:
        DebugWidget(QWidget * parent = Q_NULLPTR);
private:

};

#endif`



`#include "debugwidget.hpp"
#include <iostream>
#include <vector>
#include <string>
#include <ostream>
#include <fstream>

DebugWidget::DebugWidget(QWidget * parent) : QWidget(parent) {

        //setWindowFlags(Qt::WindowStaysOnTopHint);
        resize(1100,800);
        //setAttribute(Qt::WA_DeleteOnClose, true);

}

DebugWidget::~DebugWidget() {

}
#include <QWidget>
#include <qtextedit.h>
#include <qlayout.h>
#include "debugwidget.hpp"
class DebugText : public DebugWidget {
        Q_OBJECT

public:

        ~DebugText();
        void addContents(const QString& s1);
        static DebugText* getDebugText();


private:
        QTextEdit *ShowDebugArea;
        QHBoxLayout *qlayout;

        DebugText(DebugWidget * parent = Q_NULLPTR);


};
extern DebugText *dt;

#endif`





`#include "debugtext.hpp"
#include "debugwidget.hpp"
#include <iostream>
#include <vector>
#include <string>
#include <ostream>
#include <fstream>

static DebugText *dt = NULL;

DebugText::DebugText(DebugWidget * parent) : DebugWidget(parent) {


        qlayout = new QHBoxLayout(this);
        ShowDebugArea = new QTextEdit(this);
        ShowDebugArea->setFontPointSize(18);
        qlayout->setAlignment(Qt::AlignCenter);
        qlayout->addWidget(ShowDebugArea);

        show();
}

DebugText::~DebugText() {
}

void DebugText::addContents(const QString& s1)
{
        ShowDebugArea->append(s1);
        show();
}

DebugText* DebugText::getDebugText() {
        if (dt == NULL)
                dt = new DebugText;
        return dt;
}`

该类是自己定义的输出类,作用是开一个窗口,然后在上面显示东西。该类在前面自定义调试器的部分已经说过了。

我们的多线程方式采用继承多线程类,然后里面的run,即在另一个线程里启动的函数。注意该函数不用直接调用,直接使用QThread::start(),就会自动调用该函数。

`#pragma once
#ifndef __MULTITHREAD_H__
#define __MULTITHREAD_H__
#include <QThread>

class MultiThread : public QThread {
        Q_OBJECT

public:
        MultiThread(QObject * parent = Q_NULLPTR);
        ~MultiThread();

        void run();
private:


};
#include "multithread.hpp"
#include "Debugtext.hpp"

MultiThread::MultiThread(QObject * parent) : QThread(parent) {

}

MultiThread::~MultiThread() {

}

void MultiThread::run()
{
        int i = 10;
        while (i--) {
                DebugText::getDebugText()->addContents("aaaaaaa");

        }

}`

注意,DebugText类只是一个普通的类,它并没有任何使用多线程的机制。

`#include "multithread.hpp"
#include <QApplication>
#include "Debugtext.hpp"
int main(int argc, char *argv[])
{
        QApplication a(argc, argv);

        MultiThread  mythread;
        mythread.start();

        int i = 10;
        while (i--) {
                DebugText::getDebugText()->addContents("bbbbbb");

        }	

        return a.exec();
}`

然后运行:内存访问出错。

这是为什么呢?因为我们的DebugText的核心函数就是在TextEdit控件里添加显示字符串,而如果两个线程同时去访问了这个对象,则就会出现访问错误的情况。

我们改改主函数:

`#include "multithread.hpp"
#include <QApplication>
#include "Debugtext.hpp"
int main(int argc, char *argv[])
{
        QApplication a(argc, argv);

        MultiThread  mythread;

        //mythread.terminate();
        int i = 10;
        while (i--) {
                DebugText::getDebugText()->addContents("bbbbbb");

        }	
        mythread.start();
        //QThread::sleep(100);
        return a.exec();
}`

这样,就可以发现,我们先打印了一堆bbbbbbb,然后又打印了一堆aaaaaaa,

但是这样好像并没有什么意义,因为我们是想同时让bbbbbbb和aaaaaaaa被打印出来。否则就是先执行一个再执行另一个,这就不是多线程了。

为了实现可以多个线程同时调用DebugText,我们必须对这个DebugText加入多线程的机制,这会在下一节进行介绍。