最近项目中用到线程框架,需要主线程等待所有子线程执行完毕,小编突发奇想,结合设计模式中的复合模式和装饰模式写了这个deamo,这个例子最大的特点是,它不但可以实现最基本的需求,它还拥有像junit一样灵活的使用方法。
以下是源代码和详解:
importjava.util.List;
importjava.util.Vector;
publicclassThreadSuiteextendsThread {
privateList threadUnits =newVector();
privateintthreadCount =0;
privatebooleanwaitEnable =true;
privatelongtimeout =0;
private boolean excuteEnable = true;
publicThreadSuite() {
}
publicThreadSuite(longtimeout) {
this.timeout = timeout;
}
publicThreadSuite(String threadName) {
super(threadName);
}
publicThreadSuite(String threadName,longtimeout) {
super(threadName);
this.timeout = timeout;
}
@Override
publicvoidrun() {
synchronized(this) {
for(ThreadUnit threadUnit : threadUnits) {
if (!threadUnit.isAlive()) {
threadUnit.start();
}
}
if(waitEnable) {
try{
this.wait(timeout);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
publicsynchronizedvoidadd(ThreadUnit threadUnit) {
threadCount++;
threadUnit.setThreadSuite(this);
threadUnits.add(threadUnit);
}
publicsynchronizedvoidanotice() {
threadCount--;
if(threadCount <1) {
waitEnable =false;
this.notify();
}else{
waitEnable =true;
}
}
publicvoidexcute() {
if (excuteEnable) {
excuteEnable = false;
this.run();
}
}
}
publicclassThreadUnitextendsThread {
privateThreadSuite threadSuite =null;
privateThread thread =null;
publicThreadUnit(Thread thread) {
this.thread = thread;
}
@Override
publicvoidrun() {
try{
this.thread.run();
}catch(Exception e) {
}finally{
if (threadSuite != null) {
threadSuite.anotice();
}
}
}
publicvoidsetThreadSuite(ThreadSuite threadSuite) {
this.threadSuite = threadSuite;
}
}
importjava.util.Random;
publicclassThreadTestextendsThread {
privateRandom random =newRandom();
publicThreadTest(String threadName) {
super(threadName);
}
@Override
publicvoidrun() {
System.out.println(newStringBuffer("Thread: ").append(
this.getName()).append(" begin."));
try{
Thread.sleep(random.nextInt(1000) +2000);
}catch(InterruptedException e) {
}
System.out.println(newStringBuffer("Thread: ").append(
this.getName()).append(" end."));
}
}
importjava.util.ArrayList;
importjava.util.List;
publicclassProgram {
publicstaticvoidmain(String[] args) {
List list =newArrayList();
ThreadSuite ts1 = getThreadSuite("a",5);
ThreadSuite ts2 = getThreadSuite("b",5);
list.add(newThreadUnit(ts1));
list.add(newThreadUnit(ts2));
ThreadSuite threadSuite =newThreadSuite();
for(ThreadUnit tu : list) {
threadSuite.add(tu);
}
// threadSuite.excute();
ts1.excute();
ts2.excute();
System.out.println("main end.");
}
publicstaticThreadSuite getThreadSuite(String threadMark,intthreadCount) {
List list =newArrayList();
for(inti =1; i <= threadCount; i++) {
list.add(newThreadUnit(newThreadTest(threadMark + i)));
}
ThreadSuite threadSuite =newThreadSuite();
for(ThreadUnit tu : list) {
threadSuite.add(tu);
}
returnthreadSuite;
}
}
如果main方法中最后几行的代码是这样的:
// threadSuite.excute();
ts1.excute();
ts2.excute();
System.out.println("main end.");
则执行结果为:
Thread: a2 begin.
Thread: a1 begin.
Thread: a3 begin.
Thread: a5 begin.
Thread: a4 begin.
Thread: a2 end.
Thread: a5 end.
Thread: a4 end.
Thread: a1 end.
Thread: a3 end.
Thread: b1 begin.
Thread: b3 begin.
Thread: b5 begin.
Thread: b2 begin.
Thread: b4 begin.
Thread: b4 end.
Thread: b1 end.
Thread: b2 end.
Thread: b3 end.
Thread: b5 end.
main end.
如果main方法中最后几行的代码是这样的:
threadSuite.excute();
// ts1.excute();
// ts2.excute();
System.out.println("main end.");
则执行结果为:
Thread: b1 begin.
Thread: a1 begin.
Thread: a2 begin.
Thread: a3 begin.
Thread: a4 begin.
Thread: a5 begin.
Thread: b2 begin.
Thread: b3 begin.
Thread: b4 begin.
Thread: b5 begin.
Thread: b5 end.
Thread: b4 end.
Thread: b3 end.
Thread: b1 end.
Thread: a1 end.
Thread: a2 end.
Thread: a5 end.
Thread: a4 end.
Thread: b2 end.
Thread: a3 end.
main end.
从以上执行结果可以看出:
ThreadSuite类的excute()方法其实是直接调用了它自身的run方法,并且ThreadSuite线程类会等待所有加入到它的管理队列中的Thread类执行完毕后,它的run方法才会运行完毕。因此,完全可以把ThreadSuite类当成是普通的Thread类对待,这样的话,可以把生成的多个ThreadSuite类实例当作普通线程类经过ThreadUnit类包装后放入新的ThreadSuite类管理队列当中
需要注意的是:
这个deamo其实也不算是个完全的复合模式,因为子线程是经过ThreadUnit类装饰过的,但是你也完全可以理解为:是ThreadSuite类对Thread类的复合,因为Thread类也是ThreadUnit类的父类,也就是说向上转型。在每一个Thread类实例经过ThreadUnit类包装后并加入到ThreadSuite类管理队列中时,ThreadSuite类会把当前线程计数加1。ThreadUnit类其实是Thread类的一个包装类,它会在加入到它的Thread类实例的run方法运行完毕后调用ThreadSuite类的anotice()方法通知ThreadSuite类自己的线程任务已经完成,并请求线程计数减1,这样的话,ThreadSuite类会判断当前所有的加入到它的管理队列中的线程是否全部执行完毕,如果执行完毕,它会调用自身的notice()方法停止等待。如果加入到ThreadSuite类管理队列中的所有Thread类执行完毕后,ThreadSuite类才调用它自身的wait()方法(这种情况出现的几率很小),这样的话,ThreadSuite类会一直等待下去,直到等待超时,因为已经没有可用的Thread类试图唤醒ThreadSuite类的等待,为了防止这种情况出现,ThreadSuite类引入了waitEnable字段,它的初始值是true,当线程计数小于1的时候,它会被设为false,这样的话,在所有的Thead类执行完毕后,ThreadSuite类的wait()方法将不会被调用。