(转载自:
http://blog.youkuaiyun.com/u011314012/article/details/49993659)
通常情况下,应用程序都是在一个线程中执行操作。但是,当调用一个耗时操作(例如,大批量I/O或大量矩阵变换等CPU密集操作)时,用户界面常常会冻结。而使用
多线程可解决这一问题。
多线程具有以下几点优势。
(1)提高应用程序的响应速度。这对于开发图形界面的程序尤为重要,当一个操作耗时很长时,整个系统都会等待这个操作,程序就不能响应键盘、鼠标、菜单等的操
作,而是使用了多线程技术可将耗时长的操作置于一个新的线程,从而避免以上的问题。
(2)使多CPU系统更加有效。当线程数不大于CPU数目时,操作系统可以调度不同的线程运行于不同的CPU上。
(3)改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为独立或半独立的运行部分,这样有利于代码的理解和维护。
多线程程序有以下几个特点。
(1)多线程程序的行为无法预期,当多次执行上述程序时,每一次的运行结构都可能不同。
(2)多线程的执行顺序无法保证,它与操作系统的调度策略和线程优先级等因素有关。
(3)多线程的切换可能发生在任何时刻、任何地点。
(4)多线程对代码的敏感度高,因此对代码的细微修改都可能产生意想不到的结果。
基于以上这些特点,为了有效地使用线程,开发人员必须对其进行控制。
12.1 多线程及简单实例
点击“开始”按钮将启动数个工作线程(工作线程数目由MAXSIZE宏决定),各个线程循环打印数字0-9.直到按下“停止”按钮终止所有线程为止。
运行效果:
threaddlg.h
#ifndef THREADDLG_H
#define THREADDLG_H
#include <QDialog>
#include <QPushButton>
#include "workthread.h"
#define MAXSIZE 5
class ThreadDlg : public QDialog
{
Q_OBJECT
public:
ThreadDlg(QWidget *parent = 0);
~ThreadDlg();
private:
QPushButton *startBtn;
QPushButton *stopBtn;
QPushButton *exitBtn;
public slots:
void slotstart(); //启动线程槽函数
void slotstop(); //终止线程槽函数
private:
WorkThread *workThread[MAXSIZE]; //指向工作线程的私有指针数组,记录了所启动的全部线程
};
#endif // THREADDLG_H
threaddlg.cpp
#include "threaddlg.h"
#include <QHBoxLayout>
ThreadDlg::ThreadDlg(QWidget *parent)
: QDialog(parent)
{
setWindowTitle(tr("线程"));
startBtn = new QPushButton(tr("开始"));
stopBtn = new QPushButton(tr("停止"));
exitBtn = new QPushButton(tr("退出"));
QHBoxLayout *mainLayout = new QHBoxLayout(this);
mainLayout->addWidget (startBtn);
mainLayout->addWidget (stopBtn);
mainLayout->addWidget (exitBtn);
startBtn->setEnabled (true);
stopBtn->setEnabled (true);
connect (startBtn, SIGNAL(clicked(bool)), this, SLOT(slotstart()));
connect (stopBtn, SIGNAL(clicked(bool)), this, SLOT(slotstop()));
connect (exitBtn, SIGNAL(clicked(bool)), this, SLOT(close()));
}
ThreadDlg::~ThreadDlg()
{
}
/*
* 这里使用两个循环,目的是为了使新建的线程尽可能开始执行
*/
void ThreadDlg::slotstart ()
{
for(int i = 0; i < MAXSIZE; i++)
{
workThread[i] = new WorkThread();
}
for(int i = 0; i < MAXSIZE; i++)
{
workThread[i]->start ();
}
startBtn->setEnabled (false);
stopBtn->setEnabled (true);
}
/*
* workThread[i]->terminate ()、 workThread[i]->wait ():调用QThread基类的terminate()函数,依次终止保存在
* workThread[]数组中的WorkThread类实例。但是terminate()函数并不会立刻终止这个线程,该线程何时终止取决于操作系统的
* 调度策略。因此,程序紧挨着调用了QThread基类的wait()函数,它使得线程阻塞等待直到退出或超时。
*/
void ThreadDlg::slotstop ()
{
if(!startBtn->isEnabled())
{
for(int i = 0; i < MAXSIZE; i++)
{
workThread[i]->terminate ();
workThread[i]->wait ();
}
startBtn->setEnabled (true);
stopBtn->setEnabled (false);
}
}
workthread.h
#ifndef WORKTHREAD_H
#define WORKTHREAD_H
#include <QThread>
class WorkThread : public QThread
{
public:
WorkThread();
protected:
void run();
};
#endif // WORKTHREAD_H
workthread.cpp
#include "workthread.h"
#include <QDebug>
WorkThread::WorkThread()
{
}
void WorkThread::run ()
{
while(true)
{
for(int