最近项目中用到线程框架,需要主线程等待所有子线程执行完毕,小编突发奇想,结合设计模式中的复合模式和装饰模式写了这个deamo,这个例子最大的特点是,它不但可以实现最基本的需求,它还拥有像junit一样灵活的使用方法。

 以下是源代码和详解:

   
   
   
   
  1. import java.util.List;  
  2. import java.util.Vector;  
  3.  
  4. public class ThreadSuite extends Thread {  
  5.     private List threadUnits = new Vector();  
  6.     private int threadCount = 0;  
  7.     private boolean waitEnable = true;  
  8.     private long timeout = 0;
  9. private boolean excuteEnable = true;
  10.  
  11.     public ThreadSuite() {  
  12.     }  
  13.     public ThreadSuite(long timeout) {  
  14.         this.timeout = timeout;  
  15.     }  
  16.     public ThreadSuite(String threadName) {  
  17.         super(threadName);  
  18.     }  
  19.     public ThreadSuite(String threadName, long timeout) {  
  20.         super(threadName);  
  21.         this.timeout = timeout;  
  22.     }  
  23.     @Override 
  24.     public void run() {  
  25.         synchronized (this) {  
  26.             for (ThreadUnit threadUnit : threadUnits) {  
  27.                 if (!threadUnit.isAlive()) {
          threadUnit.start();
         }
  28.             }  
  29.             if (waitEnable) {  
  30.                 try {  
  31.                     this.wait(timeout);  
  32.                 } catch (InterruptedException e) {  
  33.                     e.printStackTrace();  
  34.                 }  
  35.             }  
  36.         }  
  37.     }  
  38.     public synchronized void add(ThreadUnit threadUnit) {  
  39.         threadCount++;  
  40.         threadUnit.setThreadSuite(this);  
  41.         threadUnits.add(threadUnit);  
  42.     }  
  43.     public synchronized void anotice() {  
  44.         threadCount--;  
  45.         if (threadCount < 1) {  
  46.             waitEnable = false;  
  47.             this.notify();  
  48.         } else {  
  49.             waitEnable = true;  
  50.         }  
  51.     }  
  52.     public void excute() {  
  53.         if (excuteEnable) {
        excuteEnable = false;
        this.run();
       }
  54.     }  
  55. }  
  56.  
  57. public class ThreadUnit extends Thread {  
  58.     private ThreadSuite threadSuite = null;  
  59.     private Thread thread = null;  
  60.     public ThreadUnit(Thread thread) {  
  61.         this.thread = thread;  
  62.     }  
  63.     @Override 
  64.     public void run() {  
  65.         try {  
  66.             this.thread.run();  
  67.         } catch (Exception e) {  
  68.         } finally {  
  69.             if (threadSuite != null) {
         threadSuite.anotice();
        }
  70.         }  
  71.     }  
  72.     public void setThreadSuite(ThreadSuite threadSuite) {  
  73.         this.threadSuite = threadSuite;  
  74.     }  
  75. }  
  76.  
  77. import java.util.Random;  
  78. public class ThreadTest extends Thread {  
  79.     private Random random = new Random();  
  80.     public ThreadTest(String threadName) {  
  81.         super(threadName);  
  82.     }  
  83.     @Override 
  84.     public void run() {  
  85.         System.out.println(new StringBuffer("Thread:    ").append(  
  86.                 this.getName()).append("       begin."));  
  87.         try {  
  88.  
  89.             Thread.sleep(random.nextInt(1000) + 2000);  
  90.         } catch (InterruptedException e) {  
  91.         }  
  92.         System.out.println(new StringBuffer("Thread:    ").append(  
  93.                 this.getName()).append(" end."));  
  94.     }  
  95. }  
  96.  
  97. import java.util.ArrayList;  
  98. import java.util.List;  
  99. public class Program {  
  100.     public static void main(String[] args) {  
  101.         List list = new ArrayList();  
  102.         ThreadSuite ts1 = getThreadSuite("a"5);  
  103.         ThreadSuite ts2 = getThreadSuite("b"5);  
  104.         list.add(new ThreadUnit(ts1));  
  105.         list.add(new ThreadUnit(ts2));  
  106.         ThreadSuite threadSuite = new ThreadSuite();  
  107.         for (ThreadUnit tu : list) {  
  108.             threadSuite.add(tu);  
  109.         }  
  110. //      threadSuite.excute();  
  111.         ts1.excute();  
  112.         ts2.excute();  
  113.         System.out.println("main end.");  
  114.     }  
  115.     public static ThreadSuite getThreadSuite(String threadMark,int threadCount) {  
  116.         List list = new ArrayList();  
  117.         for (int i = 1; i <= threadCount; i++) {  
  118.             list.add(new ThreadUnit(new ThreadTest(threadMark + i)));  
  119.         }  
  120.         ThreadSuite threadSuite = new ThreadSuite();  
  121.         for (ThreadUnit tu : list) {  
  122.             threadSuite.add(tu);  
  123.         }  
  124.         return threadSuite;  
  125.     }  

 如果main方法中最后几行的代码是这样的:

   
   
   
   
  1. //      threadSuite.excute();  
  2.         ts1.excute();  
  3.         ts2.excute();  
  4.         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方法中最后几行的代码是这样的:

 

   
   
   
   
  1.         threadSuite.excute();  
  2. //      ts1.excute();  
  3. //      ts2.excute();  
  4.         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()方法将不会被调用。