您的位置:首页 > 编程语言 > Qt开发

Qt QThread 线程创建,线程同步,线程通信 实例

2013-08-22 13:20 423 查看
1. 继承QThread, 实现run()方法, 即可创建线程。



2. 实例1 代码

myThread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>

class myThread : public QThread   //myThread 线程类
{
Q_OBJECT

public:
myThread();
void setMessage(const QString &message);
void stop();
protected:
void run();   //复写run()方法,里面是线程 的 主体代码
private:
QString messageStr;
volatile bool stopped;
};

#endif // MYTHREAD_H

myThread.cpp

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

myThread::myThread()
{
stopped = false;
}

void myThread::run()  //实现run()方法, 隔1秒输出messageStr
{
while(!stopped)
{
qDebug() << messageStr << endl;
sleep(1);
}
stopped = false;
}

void myThread::stop()
{
stopped = true;
}

void myThread::setMessage(const QString &message)
{
messageStr = message;
}

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QtGui>
#include "myThread.h"

class Dialog : public QDialog
{
Q_OBJECT

public:
Dialog(QWidget *parent = 0);
~Dialog();

protected:
void closeEvent(QCloseEvent *event);

private slots:
void startOrStopThreadA();
void startOrStopThreadB();

private:
myThread threadA;   //用线程类 实例化 线程对象
myThread threadB;
QPushButton *threadAButton;
QPushButton *threadBButton;
QPushButton *quitButton;
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
threadA.setMessage("A");
threadB.setMessage("B");

threadAButton = new QPushButton(tr("Start A"));
threadBButton = new QPushButton(tr("Start B"));
quitButton = new QPushButton(tr("Quit"));
quitButton->setDefault(true);
connect(threadAButton, SIGNAL(clicked()), this, SLOT(startOrStopThreadA()));
connect(threadBButton, SIGNAL(clicked()), this, SLOT(startOrStopThreadB()));
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));

QHBoxLayout *hLayout = new QHBoxLayout;
hLayout->addWidget(threadAButton);
hLayout->addWidget(threadBButton);
hLayout->addWidget(quitButton);
setLayout(hLayout);
}

Dialog::~Dialog()
{
}

void Dialog::startOrStopThreadA()
{
if( threadA.isRunning() )
{
threadA.stop();   //结束线程
threadAButton->setText(tr("Start A"));
}
else
{
threadA.start();   //thread.start()开始线程
threadAButton->setText(tr("Stop A"));
}
}

void Dialog::startOrStopThreadB()
{
if( threadB.isRunning() )
{
threadB.stop();
threadBButton->setText(tr("Start B"));
}
else
{
threadB.start();
threadBButton->setText(tr("Stop B"));
}
}

void Dialog::closeEvent(QCloseEvent *event)  //当用户点击quit按键  或 这退出UI的时候,回调closeEvent函数
{
threadA.stop();
threadB.stop();
threadA.wait();
threadB.wait();
event->accept();
//qDebug("--log--");
}


3. 线程同步

QT线程同步的类有: QMutex, QReadWriteLock, QSemaphore, QWaitcondition.

QMutext互斥锁: 可以锁住一段代码,同一时间只能有一个线程访问。



或者用简化锁QMutexLocked类, 构造函数输入QMutex并将其锁住, 析构函数将其解锁。



QReadWriteLock类, 允许多个线程读共享资源,但是只允许一个线程写共享资源。



QSemaphore 信号量 互斥量, 解决 生产者--消费者 问题





4. 利用信号槽, 主线程和子线程通信,互相发送消息。



子线程向主线程发送 每隔一秒向主线程发送累加数字, 主线程按键信息发送到子线程。。

Thread.h

#ifndef THREAD_H
#define THREAD_H
#include <QThread>

class Thread : public QThread
{
Q_OBJECT
private:
int number;
protected:
void run();
public:
Thread(QObject *parent=0);
~Thread();
signals:
void UpdateSignal(int num);
public slots:
void ResetSlot();
};

#endif // THREAD_H


Thread.cpp

#include "Thread.h"

Thread::Thread(QObject *parent)
{
number = 0;
}

Thread::~Thread()
{
}

void Thread::run()
{
while(1)
{
emit UpdateSignal(number);  //发送更新信号给主线程,附带参数number
number++;
sleep(1);
}
}

void Thread::ResetSlot()
{
number = 0;
emit UpdateSignal(number);  //发送重置number信号
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QtGui>
#include "Thread.h"

class Widget : public QWidget
{
Q_OBJECT

public:
Widget(QWidget *parent = 0);
~Widget();

private:
QLabel *label;
QPushButton *startButton;
QPushButton *stopButton;
QPushButton *resetButton;
Thread *myThread;
int number;

signals:
void ResetSignal();

public slots:
void clearSlot();
void startSlot();
void stopSlot();
void updateSlot(int num);

};

#endif // WIDGET_H

widget.cpp

#include "widget.h"

Widget::Widget(QWidget *parent)
: QWidget(parent)
{
startButton = new QPushButton("start");
stopButton = new QPushButton("stop");
resetButton = new QPushButton("reset");
label = new QLabel("empty");

myThread = new Thread();

QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(label);
layout->addWidget(startButton);
layout->addWidget(stopButton);
layout->addWidget(resetButton);
setLayout(layout);

connect(stopButton, SIGNAL(clicked()), this, SLOT(stopSlot()));
connect(startButton, SIGNAL(clicked()), this, SLOT(startSlot()));
connect(resetButton, SIGNAL(clicked()), this, SLOT(clearSlot()));
connect(myThread, SIGNAL(UpdateSignal(int)), this, SLOT(updateSlot(int)));   //子线程发信号给主线程,更新number
connect(this, SIGNAL(ResetSignal()), myThread, SLOT(ResetSlot()));   //主线程发信号给子线程,重置number信号

resize(200, 200);

}

Widget::~Widget()
{

}

void Widget::startSlot()
{
myThread->start();
}

void Widget::stopSlot()
{
myThread->terminate();
}

void Widget::updateSlot(int num)
{
label->setText(QString::number(num));
}

void Widget::clearSlot()
{
emit ResetSignal();     //主线程发送重置信号 给 子线程
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: