转自:
http://mobile.51cto.com/symbian-271152.htm
http://mobile.51cto.com/symbian-271159.htm
我总觉得学一个东西时候,我们应该保留最简单本质的东西,接着做个demo的程序先跑起来,再慢慢学入进去.这样一来难度也不会那么大,有时我们也需要自我陶醉一翻,有点成就感了,才能有动力下去。
每个操作系统平台和语言都有自己创建线程的办法,可我们精力有限,不可能一个个全都知道和去学,一般工作也就是掌握一两个.幸好现在有QT,免去平台差异的东西。qt大概从3.x后就开始有了线程支持,到了4.x的时候更是加入了更多高级功能,比如跨线程signal/slot,线程消息循环等,这也为我们做线程通信提供了很好的环境.
在QT要使用线程的话,必须从QThread派生一个类,这是规定,哪怕你的线程做的事情简单到1+1都得这么做.。这次我们先做个简单的程序,让一个多线程程序跑起来,其他的留到以后再说.
使用一个线程的主要的步骤如下:
1、定义一个线程类,继承自QThread
2、重载protected Run方法
3、实例化类,用QThread 的Start方法 ,开始跑起线程,这样最终创建的线程将和主线程就并发运行了
CTHREAD.H
- #ifndef CTHREAD_H
- #define CTHREAD_H
- #include <QThread>
- class CThread : public QThread
- {
- public:
- CThread();
- protected:
- void run();
- };
- #endif // CTHREAD_H
CTHREAD.cpp
- #include "CThread.h"
- #include <QDebug>
- CThread::CThread():QThread()
- {
- }
- void CThread::run()
- {
- for(int i=1;i<=10000;i++)
- qDebug()<<i;
- }
线程创建完了之后必须要对其进行限制和控制,我们就是线程的监护人,不能说任由它自由,得对它进行合理约束。接下来我们讲线程的控制部分,
1、线程休眠
想象一下一种情形,日常用的电脑,如果我们需要离开一段时间,那么可能会将它暂时休眠一下,为了节约用电,也响应一下环境保护,别忘了现在都讲低炭生活。那么线程其实也一样,如果一个线程暂时不需要用到,我们可以先让它睡会,其目的也是为了让它暂时不要占用资源,主要是一个cpu时间片的占用问题。
对于线程的休眠,只要简单调用 Qthread 的sleep ,msleep或者usleep 方法就可以了,注意这三个方法都是Static Protected的,这意味着你只能在继承类里做这个动作,它们差别仅是时间单位不同而已。
程序方面我们尽量简单点,能看清本质就可以了,在Qthread 派生类的Run方法里面用下
- void CThread::run()
- {
- for(int i=1;i<=10000;i++)
- {
- qDebug()<<i;
- sleep(1); //请不要那么快,睡一下再往下执行
- }
- }
2、线程唤醒
既然有线程的休眠,那就有唤醒。如果你已经和线程说 Sleep 10秒吧,突然人家睡到一半的时候,你又改变主意想让它醒过来,这里我要抱歉的说声是没办法的,它就像猪一样,没到时间是不会醒的。比较合适的方案就是线程同步能够解决这样的问题,这个放到 下一篇 线程的同步[1/2] 的时候再说.只要记住sleep是强制休眠就可以,但现在没办法提供强制唤醒的办法.
3、线程关闭
如果一个线程运行完了它会自己结束自己的生命。可很多情况不是这么简单,一个线程跑到中间的时候由于某种特殊原因,就想它中止。
(1)线程中止方式
中止有两种方式 强制中止和 优雅中止,这用词可能有点不恰当,先这么说着。在说明这两种方式之前,有必要详细说一下线程关闭的时候它到底干了什么。
线程关闭的时候,OS会移除这个线程,这部分对我们是透明的,详细的说明还得参阅操作系统的有关书籍,接着线程中分配的堆栈信息将一并清除,但是如果是堆上分配的信息,得由你负责自己清除,因为堆是由进程持有的,它的生命周期和线程没关系。
(2)强制中止:
简单的调用Qthread 的方法terminate就可以进行强制中止,可这将会带来很多灾难性的后果。最为严重的就是一个堆内存泄露的问题,线程强制被中止,根本没法来得及做清理工作,即使你的线程 中有执行到最后清理堆内存,可它没来得及执行
比如以下一段代码
- void CThread::run()
- {
- int *c = new int;
- for(int i=1;i<=10000;i++)
- {
- qDebug()<<i;
- }
- //clean
- delete c;
- }
想象一下线程还没执行 到 delete c;的时候你就发出了terminate,不幸的事就发生了,由此得出结论我们应该尽最大限度避免去使用。
(3)优雅的中止:
那么怎么优雅的关闭线程呢?我们应该通知线程,让线程自己去接手关闭,各自关注自己所需的事,就都能做得更好,一手抓就会带来很多问题
那么怎么通知线程呢? 一般会采用以下的步骤
1.在Qthread中派生类 定义一个公用方法出来 供中止时调用,比如stop()
2.调用者 直接 调用stop方法
3.派生类stop方法 ,设置 中止标志,一般就是bool成员
4.run方法 运行的时候,检查bool成员,判断是否需要退出进程,最后做清理工作
- //CThread.h
- #ifndef CTHREAD_H
- #define CTHREAD_H
- #include <QThread>
- class CThread : public QThread
- {
- public:
- CThread();
- ~CThread();
- void stop();
- protected:
- void run();
- private:
- bool mStop;
- };
- #endif // CTHREAD_H
- //CThread.cpp
- #include <QDebug>
- #include "CThread.h"
- CThread::CThread():QThread(),mStop(false)
- {
- }
- CThread::~CThread()
- {
- stop();
- }
- void CThread::run()
- {
- int *c = new int;
- for(int i=1;i<=10000;i++)
- {
- if (mStop) // determine to exit the loop
- {
- break;
- }
- qDebug()<<i;
- sleep(1);
- }
- //clean up
- delete c;
- }
- void CThread::stop()
- {
- mStop = true;
- wait();
- }