ZThread中,有个抽象基类Runnable,提供了一个公共接口来执行任务:
class Runnable
{
public:
virtual void run() = 0;
vitural ~Runnable(){}
};
只要从这个类继承,并且重写run()函数,就可以定义一个任务了!!!即具备了多线程的基础。
但是只是定义了一个任务,它并不具有线程处理的能力。还要推它一把。
要使用一个线程,必须要先初始化一个线程,并用Runnable* 类型的对象来构造该线程。该线程在构造函数中会自动调用run()函数,此时,main()函数与run()函数齐飞,秋水共长天一色。
请时刻记住,多线程的程序跟普通程序有不同之处,请看下面一段代码
class test : public Runnable
{
int id;
public:
test(int i = 0) : id(i){}
void run()
{
cout <<" Do Something " << endl;
}
};
int main()
{
try{
for( int i = 0; i < 5; i++ )
Thread t(new test(i));//看这里看这里,小痘痘没有了!!!
}catch(Synchronization_Exception& e){
cerr << e.what() << endl;
}
}
按理说,t是个局部变量,每次循环,t都会被自动释放掉。这里会不会这个线程对象就没有了呢?从结果上来看,答案是,不会!从原理上来看是,当创建了一个Thread对象的时候,相关联的线程会在线程处理系统中自动注册,并保持其活动状态。基于栈的对象被抛弃,但是线程本身还是活在线程处理系统中。
如果这么说的话,那么这种情况就有点像,t是一个引用,指向线程处理系统中的实际对象。引用被咔嚓掉,实例还在。从结果上看是这样的。我这么解释,是便于理解。
一个线程想做两个任务的话是不行滴,做了个很无聊的实验,想看看线程处理系统中的实际对象是个嘛
Thread t(new test(1));
Thread t(new test(1));
//----------华丽丽的分割线-----------错误,t重定义了//
{
Thread t(new test(1));
}
{
Thread t(new test(1));
}
//----------华丽丽的分割线-----------正常,两个线程, 两个不同的任务//
test* tp = new test;// same task
Thread t1(tp);
Thread t2(tp);
//----------华丽丽的分割线-----------非常正常,两个线程完成一个任务//
以上实验说明,栈上的名字真的不重要!!!
通过多线程,可以创建一个有响应的用户界面。具体程序就不在码了,这里要说的是有两个问题:1. 怎么退出一个线程 2. 线程间通信。
1. 怎么退出?正常退出,强制退出(包括中断),带来的问题是,非正常退出的话资源不不会释放?
2. 线程间通信,发送一个信号,让子线程正常退出。
考虑下面这段代码:
test* tp = new test;
Thread t1(tp);
delete tp;// 这相当于釜底抽薪,太绝了
千万别这么做,除非你跟你的公司有不共戴天之仇。这么做的问题在于,你不知道你的线程正在用tp做多么重要的事情,突然tp就这么没了,线程也会傻在那里。最终导致代码的不稳定。不稳定懂么,公司都需要稳定的代码。
那么想要一个线程停下来,就让它自己决定是否应该停,这时候它会清理现场,释放堆栈之类的,总之,妥妥的。
总结就是:给他一个flag,让他自己决定是否退出,千万别随便决定别人的命运。
使用执行器简化工作
其实没看出来有什么简化的,就是不用Thread的构造函数了,用一个executor.execute(Runnable*)函数来做,该函数的参数也是一个Runnable类型的指针。语义上比较好理解了吧。还没有理解其真正的涵义。
执行器每次都要创建线程,比较耗时耗资源。另外一种方法就是一次创建一堆线程,等你要用的时候就从线程池里面去取。该方法用PoolExecutor,示例代码:
#include "zthread/PoolExecutor.h"
..
..
..
PoolExecutor executor(5);
for(int i = 0; i < 5; i++)
executor.execute(new test(i));
..
..
concurrentExecutor 所有的任务用一个线程,当一个任务执行完毕之后,后一个任务才开始执行,示例代码:
#include"zthread/ConcurrentExecutor.h"
//..
ConcurrentExecutor executor;
for(int i = 0; i < 5; i++ )
executor.execute(new test(i));//任务按提交顺序执行,在下一个任务开始之前执行完成
字体越来越小了 肿么回事
让步
yield()告诉CPU, 我做完了要做的事情,你可以让别人跑了。
sleep()告诉CPU, 我累了,睡会觉,你可以让别人先跑。
设置优先级,告诉CPU,我们是有等级的,让大佬先跑!!!代码示例:
#include "zhread/Thread.h"
//..Something else
Thread high(new test(1));
Thread medium(new test(2));
Thread low(new test(3));
high.setPriority(High);//总舵主
medium.setPriority(Medium);//分舵主
low.setPriority(Low);//成员
哎,有了等级,大家就更有顺序了“让领导先走!!!”
总结:创建一个任务很简单,重写run就对了。让一个线程执行一个任务很简单,构造函数中放个任务指针就对了。想要轻松执行线程很简单,用个executor帮你就对了。领导先走很简单,设个优先级就对了。下一章:共享有限资源。
posted on 2012-05-15 17:22
Dino-Tech 阅读(500)
评论(1) 编辑 收藏 引用