黑馬程式猿——12,多執行緒(2)

weixin_33912246發表於2017-04-20

------<ahref="http://www.itheima.com" target="blank">Java培訓、Android培訓、iOS培訓、.Net培訓</a>、期待與您交流! -------

              黑馬程式猿——12,多執行緒(2)

 

//執行緒之間的通訊
//就是多個執行緒操作同一個資源,操作動作不同
//舉一個樣例:一堆資源(名字,性別),一個執行緒輸入,一個執行緒輸出列印
 
class  Person
{
         String  name;
         String  sex;
}
 
class   Shuru  implements  Runnable            
{
     private  Person  p;
           Shuru( Person p   )
           {
               this.p=p;
           }
           public  void  run()
           {
                     int x= 0;
                     while(true)//特別說明:由於 while (true)這句話的關係。最後要按Ctrl+c按鍵才停下虛擬機器,否則會耗費非常多資源)        
                     {
            if(x==0)
                              {
               p.name="張三";
                          p.sex="男性";
                              }
                              else
                              {
               p.name="李四";
                          p.sex="女性";
                              }
                              x=(x+1)%2;
                     }
           }
}
class  Shuchu  implements  Runnable
{
           private Person  p;
           Shuchu( Person  p   )
           {
               this.p=p;
           }
            public  void  run()
           {
               while(true)
                     { 
                              System.out.println(p.name+"-----"+p.sex);
                     }
           }
 
}
 
class Xctx
{
         public  static  void  main(String[] args)
         {
                   Person  p=new Person();
 
                   Shuru  b1=new Shuru(p);
                   Shuchu  b2=new Shuchu(p);
 
                   Thread  c1=new Thread(b1);
                   Thread  c2=new Thread(b2);
 
                   c1.start();
             c2.start();
                   System.out.println("HelloWorld!");
         }
}
 
/*
依照一般的思路。準確的列印應該是張三相應男性,李四相應女性的
但是編譯執行的結果例如以下。出了問題:
Hello World!
李四-----男性
李四-----男性
李四-----女性
李四-----男性
張三-----女性
張三-----女性
李四-----男性
李四-----男性
張三-----男性
張三-----女性
張三-----男性
張三-----男性
李四-----男性
張三-----男性
李四-----女性
李四-----男性
張三-----男性
李四-----女性
張三-----女性
李四-----女性
李四-----男性
 
 
出問題的解決辦法是:輸入執行緒在輸入資訊的同一時候輸出執行緒也在列印,
那麼非常有可能在輸入資訊輸入到一半的時候。就被輸出執行緒列印出去了。
那麼列印出去的就是部分更新資料部分舊資料,這就相應不上了
*/

——————分析——————

//為了解決這樣的問題,我們還是能夠用同步程式碼塊來解決
/*
原理就是輸入執行緒與輸出執行緒都是對同一個物件操作。僅僅只是操作過程不一樣
那麼使用同步程式碼塊,讓兩個使用同一個鎖,這樣就限制了在某一個時刻僅僅能夠有一個執行緒對物件進行操作
等這個執行緒操作完之後下一個執行緒才幹夠對物件進行操作
確保了列印出來的物件資訊的更新是完整
*/
 
class  Person
{
         String  name;
         String  sex;
         static  Object obj=new Object();
}
 
class   Shuru  implements Runnable            
{
     private  Person  p;
           Shuru( Person p   )
           {
               this.p=p;
           }
           public  void run()
           {
                     int x= 0;
                     while(true)//特別說明:由於 while (true)這句話的關係,最後要按Ctrl+c按鍵才停下虛擬機器。否則會耗費非常多資源)
        
                     {
                              synchronized(Person.obj)//用的鎖是obj
                              {
                if(x==0)
                                {
                  p.name="張三";
                             p.sex="男性";
                                }
                                else
                                {
                   p.name="李四";
                              p.sex="女性";
                                }
                                x=(x+1)%2;
                             }
                     }
           }
 
 
}
class   Shuchu  implements  Runnable
{
           private  Person   p;
           Shuchu( Person  p   )
           {
               this.p=p;
           }
            public void run()
           {
               while(true)
                     { 
                              synchronized(Person.obj)//用的鎖是obj
                              {
                             System.out.println(p.name+"-----"+p.sex);
                              }
                     }
           }
 
}
 
class  Xctx2
{
         public  static  void  main(String[] args)
         {
                   Person  p=new Person();
 
                   Shuru  b1=new Shuru(p);
                   Shuchu  b2=new Shuchu(p);
 
                   Thread  c1=new Thread(b1);
                   Thread  c2=new Thread(b2);
 
                   c1.start();
             c2.start();
                   System.out.println("HelloWorld!");
         }
}

——————分析——————

</pre><pre name="code" class="java">//執行緒通訊中的等待喚醒機制的樣例
 
/*
等待喚醒機制,簡單的說法就是
用一個標示(通常是Boolean型的變數)
true標記輸入執行緒操作,而false標記輸出執行緒操作
輸入執行緒操作時候,輸出執行緒凍結狀態
輸出執行緒操作時候。輸入執行緒凍結狀態
這樣來保證輸出結果的準確性
這就須要用到wait()和notify()  或者是notifyAll()
*/
class  Person
{
         String  name;
         String  sex;
         static  Object obj=new Object();
         boolean  bs=true;//設定一個標示
}
 
class   Shuru  implements Runnable            
{
     private  Person  p;
           Shuru( Person p   )
           {
               this.p=p;//接收一個Person類的物件,就指向該物件。該寫法更加方便
           }
           public  void  run()
           {
                     int x= 0;
                     while(true)
//特別說明:由於 while (true)這句話的關係,最後要按Ctrl+c按鍵才停下虛擬機器。否則會耗費非常多資源)
        
                     {
                              synchronized(Person.obj)//用的鎖是obj
                              {
                if(!p.bs)
                                       {
                                               try{Person.obj.wait();}catch(Exception e){}
                                       }
                                               //wait()方法能夠凍結執行緒,該方法是定義在Object類的
                                               /*
                               這裡為什麼不直接用wait()呢?
                               由於wait()方法會丟擲一個異常所以要用try...catch
                               為什麼這裡還要在wait前面加上Person.obj這個鎖呢?
                               由於這樣的寫法:鎖.wait();   -----表示持有該鎖的執行緒要陷入沉睡。
                               也是由於這個原因,wait()方法必須在同步中才幹夠用,而notify() 
                               和notifyAll()也是由於以上原因在同步中才幹夠用。
                               其寫法也是:  鎖.notify();或者是  鎖.notifyAll();
                  
                                               */
                if(x==0)
                                {
                  p.name="張三";
                             p.sex="男性";
                                }
                                else
                                {
                  p.name="李四";
                              p.sex="女性";
                                }
                                x=(x+1)%2;
                Person.obj.notify();
                                     /*
                                     陷入沉睡的執行緒都會被扔進執行緒池
                                     notify()方法功能是喚醒在線上程池中頭一個沉睡的執行緒
                                     而notifyAll()方法則是喚醒全部沉睡的執行緒
                                     */
                 p.bs=false;
                             }
                     }
           }
 
 
}
class   Shuchu  implements  Runnable
{
           private  Person   p;
           Shuchu( Person  p   )
           {
               this.p=p;
           }
            public  void  run()
           {
               while(true)
                     { 
                              synchronized(Person.obj)//用的鎖是obj
                              {
                                       if(p.bs)
                                       {
                                                 try{Person.obj.wait();} catch(Exception e){}
                                       }
                                    
                   
                                 System.out.println(p.name+"-----"+p.sex);
                                       Person.obj.notify();
                  p.bs=true;
                              }
                     }
           }
 
}
 
class Xctx3
{
         public  static void main(String[] args)
         {
                   Person  p=new Person();
 
                   Shuru  b1=new Shuru(p);
                   Shuchu  b2=new Shuchu(p);
 
                   Thread  c1=new Thread(b1);
                   Thread  c2=new Thread(b2);
 
                   c1.start();
             c2.start();
                   System.out.println("HelloWorld!");
         }
}
/*
以上程式編譯執行結果是:
Hello World!
張三-----男性
李四-----女性
張三-----男性
李四-----女性
張三-----男性
李四-----女性
張三-----男性
李四-----女性
張三-----男性
李四-----女性
張三-----男性
李四-----女性
張三-----男性
李四-----女性
 
*/


 


補充:對於非靜態的synchronized方法,其鎖默覺得this

           對於靜態的synchronized方法。其鎖預設:為該方法所在類的類名.class     

         對於同步程式碼塊,其鎖就是括號內的東西。

——————切割線————————

//下面是程式碼優化之後的程式,更加簡潔明瞭
class  Person
{
         private  String  name;
         private  String  sex;
        
         private  boolean  bs=true;//設定一個標示
         public  synchronized  void  set( String name,String  sex   )//寫入資料的方法
         {
                   if(!bs)
                   {       
                            try{this.wait();}catch(Exception e){}
                   }
                                    
              this.name=name;
                    this.sex=sex;
                    bs=false;
                     this.notify();
         }
         public  synchronized  void  out()//列印資料的方法
         {
         if(bs)
                   {       
                            try{this.wait();}catch(Exception e){}
                   }
            System.out.println("輸出的是----"+name+"---"+sex);
                    bs=true;
                    this.notify();
         }
}
 
class   Shuru  implements  Runnable            
{
     private  Person  p;
           Shuru( Person p   )
           {
               this.p=p;
           }
           public  void  run()
           {
                     int x= 0;
                     while(true)//特別說明:由於 while (true)這句話的關係,最後要按Ctrl+c按鍵才停下虛擬機器。否則會耗費非常多資源)
        
                     {
          
               if(x==0)
                   p.set("張三","男性");
                                else
                    p.set("李四","女性");
                              
                                     x=(x+1)%2;
                           
                     }
           }
 
 
}
class  Shuchu  implements  Runnable
{
           private Person  p;
           Shuchu( Person  p   )
           {
               this.p=p;
           }
            public void run()
           {
               while(true)
                     {
                            p.out();
                     }
           }
 
}
 
class  Xctx4
{
         public  static  void  main(String[] args)
         {
                   Person  p=new Person();
 
                   newThread(new Shuru(p)).start();
             new Thread(new Shuchu(p)).start();
 
                   System.out.println("HelloWorld!");
/*
                   Shuru  b1=new Shuru(p);
                   Shuchu  b2=new Shuchu(p);
 
                   Thread  c1=new Thread(b1);
                   Thread  c2=new Thread(b2);
 
                   c1.start();
             c2.start();
                   System.out.println("HelloWorld!");
*/
         }
}

————————切割線——————

/*
多執行緒的常見生活樣例
有多個生產者生產食品,有多個消費者消化食品
每生產一個食品就消費一個食品
*/
 
class  Shipin
{
         private  int  sp=0;
         private   boolean   f=true;
         public  synchronized  void  shengchang(  )
         {
                   while(true)
                   {
        
                    while(f==false)//注意這裡用的是while所以每次執行緒從凍結狀態醒來都要檢查一次f是否是false
                       try{this.wait();} catch(Exception e){}
        sp++;
              System.out.println("生產者"+Thread.currentThread().getName()+"----"+sp);
                  
                    f=false;
                    this.notifyAll();
                    /*
                       這裡用notifyAll()方法就是為了讓全部沉睡的執行緒醒來
          既喚醒了生產者又喚醒了消費者
          此時假設f=true那麼因為之前的while作用。消費者即使是得到許可權(鎖)也不能執行僅僅能凍結,所以僅僅有一個生產者能夠得到許可權執行。
         此時假設是f=false那麼因為之前的while作用,生產者即使是得到許可權(鎖)也不能執行僅僅能凍結所以僅僅有一個消費者能夠得到許可權執行。
                    */
                   }
                  
         }
         public  synchronized  void  xiaofei(   )
         {
                   while(true)
                   {
                     while(f==true)
                       try{this.wait();} catch(Exception e){} 
 
                System.out.println("消費者"+Thread.currentThread().getName()+"----"+sp);
                  
                      f=true;
                      this.notifyAll();
                   }
         }
}
class  Shengchangzhe  implements  Runnable
{
         private  Shipin   a ;
         Shengchangzhe(Shipin   a)
         {
             this.a=a;
         }
   public void run()
         {
              a.shengchang();     
         }
}
 
class  Xiaofeizhe  implements  Runnable
{
   private  Shipin   a ;
         Xiaofeizhe(Shipin   a)
         {
             this.a=a;
         }
   public  void run()
         {
              a.xiaofei();     
         }
}
class   Xctx5
{
         public  static  void  main(String[] args)
         {
                   Shipin  a=new Shipin();
 
                   Shengchangzhe  b1=new Shengchangzhe(a);
                   Shengchangzhe  b2=new Shengchangzhe(a);
                   Xiaofeizhe     b3=new Xiaofeizhe(a);
       Xiaofeizhe     b4=newXiaofeizhe(a);
 
                   Thread  t1=new Thread(b1);
                Thread  t2=new Thread(b2);
             Thread t3=new Thread(b3);
                   Thread  t4=new Thread(b4);
 
       t1.start();
       t2.start();
             t3.start();
             t4.start();
                   System.out.println("HelloWorld!");
         }
}
/*
以上程式編譯執行結果例如以下:
生產者Thread-0----1
Hello World!
消費者Thread-3----1
生產者Thread-1----2
消費者Thread-2----2
生產者Thread-0----3
消費者Thread-3----3
生產者Thread-1----4
消費者Thread-2----4
生產者Thread-0----5
消費者Thread-3----5
生產者Thread-1----6
消費者Thread-2----6
生產者Thread-0----7
消費者Thread-3----7
生產者Thread-1----8
消費者Thread-2----8
生產者Thread-0----9
消費者Thread-3----9
生產者Thread-1----10
消費者Thread-2----10
生產者Thread-0----11
消費者Thread-3----11
生產者Thread-1----12
消費者Thread-2----12
生產者Thread-0----13
消費者Thread-3----13
生產者Thread-1----14
消費者Thread-2----14
生產者Thread-0----15
消費者Thread-3----15
生產者Thread-1----16
消費者Thread-2----16
生產者Thread-0----17
消費者Thread-3----17
生產者Thread-1----18
消費者Thread-2----18
生產者Thread-0----19
消費者Thread-3----19
生產者Thread-1----20
消費者Thread-2----20
生產者Thread-0----21
消費者Thread-3----21
生產者Thread-1----22
消費者Thread-2----22
生產者Thread-0----23
消費者Thread-3----23
生產者Thread-1----24
消費者Thread-2----24
生產者Thread-0----25
消費者Thread-3----25
生產者Thread-1----26
消費者Thread-2----26
生產者Thread-0----27
消費者Thread-3----27
生產者Thread-1----28
消費者Thread-2----28
生產者Thread-0----29
消費者Thread-3----29
生產者Thread-1----30
消費者Thread-2----30
生產者Thread-0----31
*/

——————切割線————

 

//另外一個是jdk1.5版本號升級後的情況:
import java.util.concurrent.locks.*;
//這個匯入的是後面須要用到的類
 
/*
隨著jdk1.5版本號的升級,一些新的功能也被增加。更加的方便使用者
就拿多執行緒通訊的生產者消費者樣例來說
*/
 
class   Xctx6
{
         public  static  void  main(String[] args)
         {
                   Shipin  a=new Shipin();
 
                   Shengchangzhe  b1=new Shengchangzhe(a);                
                   Xiaofeizhe     b2=new Xiaofeizhe(a);     
 
                   Thread  t1=new Thread(b1);
                   Thread  t2=new Thread(b1);
                   Thread t3=new Thread(b2);
                   Thread  t4=new Thread(b2);
 
             t1.start();
             t2.start();
             t3.start();
             t4.start();
                   System.out.println("HelloWorld!");
         }
}
class   Shipin
{
         private  int sp=0;
         private  boolean  f=true;
         private  Lock   lock=new   ReentrantLock();//將鎖作為一個物件了
 
   private  Condition  pro= lock.newCondition();
   private  Condition  con= lock.newCondition();
   /*
             Condition將Object監視器(鎖)的方法(wait,notify。notifyAll)分解成不同的物件,
                   這是為了便於與Lock組合使用。
       Lock取代synchronized方法和語句的使用(同步函式和同步程式碼塊)
                   Condition替代了Object監視器(鎖)的方法的使用。
                   Condition例項是繫結在鎖上的。一個Lock例項要獲得Condition例項就要呼叫newCondition方法。

*/ public void shengchang() throws InterruptedException { lock.lock(); try { while(f==false) pro.await();//生產者執行緒陷入凍結 //這個句式會丟擲一個InterruptedException異常 sp++; System.out.println("生產者"+Thread.currentThread().getName()+"----"+sp); f=false; con.signal();//只喚醒消費者執行緒 } finally { lock.unlock();//釋放鎖 } /* 這裡是所以要使用try...finally句型是由於確保 一定要執行 lock.unlock();也是由於前面的pro.await();會向外丟擲 一個異常,假設沒有這個句型程式就會跳出去而沒有 執行lock.unlock();這種話執行緒就沒有釋放鎖 */ } public void xiaofei() throws InterruptedException { lock.lock(); try { while(f==true) con.await();//消費者執行緒陷入凍結 System.out.println("消費者"+Thread.currentThread().getName()+"----"+sp); f=true; pro.signal();//喚醒生產者執行緒 } finally { lock.unlock(); } } } class Shengchangzhe implements Runnable { private Shipin a ; Shengchangzhe(Shipin a) { this.a=a; } public void run() { while(true) { try{a.shengchang();} catch(Exception e){} } } } class Xiaofeizhe implements Runnable { private Shipin a ; Xiaofeizhe(Shipin a) { this.a=a; } public void run() { while(true) { try{a.xiaofei();} catch(Exception e){} } } }


/*

對前面的樣例做了一個改進:

有生產者,檢查者。消費者

先要由生產者生產食品,

然後由檢查者檢測食品。

最後由消費者消化食品。

*/

import java.util.concurrent.locks.*;
 
class  Xctx7
{
         public  static  void  main(String[] args)
         {
                   Shipin  a=new Shipin();
 
                   Shengchangzhe  b1=new Shengchangzhe(a);                
                   Xiaofeizhe     b2=new Xiaofeizhe(a);
                   Jiancezhe      b3=new Jiancezhe(a);
 
                   Thread  t1=new Thread(b1);
                   Thread  t2=new Thread(b1);
                   Thread t3=new Thread(b2);
                   Thread  t4=new Thread(b2);
                   Thread t5=new Thread(b3);
                   Thread  t6=new Thread(b3);
 
 
             t1.start();
             t2.start();
             t3.start();
             t4.start();
             t5.start();
             t6.start();
                   System.out.println("HelloWorld!");
         }
}
class   Shipin
{
         private  int sp=0;
         private  int  f=1;
         private  Lock lock=new ReentrantLock();//將鎖作為一個物件了
 
   private  Condition  pro= lock.newCondition();
   private  Condition  con= lock.newCondition();
   private  Condition  jc = lock.newCondition();
 
         public    void shengchang() throws InterruptedException 
         {
                   lock.lock();
                   try
                   {
                    while(f!=1)
                             {
                             pro.await();//生產者執行緒陷入凍結
                             }
                    
        sp++;
              System.out.println("生產者"+Thread.currentThread().getName()+"----"+sp);
                  
                    f=2;
                   jc.signal();//喚醒檢測者執行緒
                   }
                   finally
                   {
                        lock.unlock();//釋放鎖
                   }       
                  
         }
         public  void  xiaofei() throws   InterruptedException 
         {
                   lock.lock();
                   try
                   {
 
                     while(f!=3)
                            {
                       con.await();//消費者執行緒陷入凍結
                            }
                           
                System.out.println("消費者"+Thread.currentThread().getName()+"----------"+sp);
                      f=1;
                      pro.signal();//喚醒生產者執行緒
                   }
                   finally
                   {
                     lock.unlock();
                   }
         }
   public  void  jiance() throws  InterruptedException  //檢測方法
         {
                   lock.lock();
                   try
                   {
 
                     while(f!=2)
                            {
                       jc.await();//檢測者執行緒陷入凍結
                           
                            }
                System.out.println("檢測者"+Thread.currentThread().getName()+"-------"+sp);
                      f=3;
                      con.signal();//喚醒消費者執行緒
                   }
                   finally
                   {
                     lock.unlock();
                   }
         }
 
}
class   Shengchangzhe  implements  Runnable
{
         privateShipin   a ;
         Shengchangzhe(Shipin   a)
         {
             this.a=a;
         }
   public   void   run()
         {
                   while(true)
                   {
                     try{a.shengchang();}
                     catch(Exception e){}
                   }
         }
}
 
class   Xiaofeizhe  implements   Runnable
{
   private   Shipin   a ;
         Xiaofeizhe(Shipin   a)
         {
             this.a=a;
         }
   public  void  run()
         {
                   while(true)
                   {
                     try{a.xiaofei();}
                     catch(Exception e){}
                   }
         }
}
class   Jiancezhe  implements Runnable
{
   private   Shipin   a ;
         Jiancezhe(Shipin   a)
         {
             this.a=a;
         }
   public   void   run()
         {
                   while(true)
                   {
                     try{a.jiance();}
                     catch(Exception e){}
                   }
         }
}
/*
以上的程式碼編譯執行結果例如以下:
生產者Thread-0----1
Hello World!
檢測者Thread-4-------1
消費者Thread-3----------1
生產者Thread-0----2
檢測者Thread-5-------2
消費者Thread-3----------2
生產者Thread-1----3
檢測者Thread-5-------3
消費者Thread-2----------3
生產者Thread-0----4
檢測者Thread-4-------4
消費者Thread-3----------4
生產者Thread-1----5
檢測者Thread-5-------5
消費者Thread-2----------5
生產者Thread-0----6
檢測者Thread-4-------6
消費者Thread-3----------6
生產者Thread-1----7
檢測者Thread-5-------7
消費者Thread-2----------7
生產者Thread-0----8
檢測者Thread-4-------8
消費者Thread-3----------8
生產者Thread-1----9
檢測者Thread-5-------9
消費者Thread-2----------9
生產者Thread-0----10
檢測者Thread-4-------10
消費者Thread-3----------10
生產者Thread-1----11
檢測者Thread-5-------11
消費者Thread-2----------11
生產者Thread-0----12
檢測者Thread-4-------12
消費者Thread-3----------12
生產者Thread-1----13
檢測者Thread-5-------13
消費者Thread-2----------13
生產者Thread-0----14
檢測者Thread-4-------14
消費者Thread-3----------14
生產者Thread-1----15
檢測者Thread-5-------15
消費者Thread-2----------15
生產者Thread-0----16
檢測者Thread-4-------16
消費者Thread-3----------16
生產者Thread-1----17
檢測者Thread-5-------17
消費者Thread-2----------17
生產者Thread-0----18
檢測者Thread-4-------18
消費者Thread-3----------18
生產者Thread-1----19
檢測者Thread-5-------19
消費者Thread-2----------19
生產者Thread-0----20
檢測者Thread-4-------20
消費者Thread-3----------20
生產者Thread-1----21
檢測者Thread-5-------21
消費者Thread-2----------21
生產者Thread-0----22
檢測者Thread-4-------22
消費者Thread-3----------22
生產者Thread-1----23
檢測者Thread-5-------23
消費者Thread-2----------23
生產者Thread-0----24
檢測者Thread-4-------24
消費者Thread-3----------24
生產者Thread-1----25
檢測者Thread-5-------25
消費者Thread-2----------25
生產者Thread-0----26
檢測者Thread-4-------26
消費者Thread-3----------26
生產者Thread-1----27
檢測者Thread-5-------27
消費者Thread-2----------27
生產者Thread-0----28
檢測者Thread-4-------28
消費者Thread-3----------28
生產者Thread-1----29
檢測者Thread-5-------29
消費者Thread-2----------29
生產者Thread-0----30
檢測者Thread-4-------30
消費者Thread-3----------30
生產者Thread-1----31
檢測者Thread-5-------31
消費者Thread-2----------31
生產者Thread-0----32
檢測者Thread-4-------32
消費者Thread-3----------32
生產者Thread-1----33
檢測者Thread-5-------33
消費者Thread-2----------33
生產者Thread-0----34
檢測者Thread-4-------34
消費者Thread-3----------34
生產者Thread-1----35
檢測者Thread-5-------35
消費者Thread-2----------35
生產者Thread-0----36
檢測者Thread-4-------36
消費者Thread-3----------36
生產者Thread-1----37
檢測者Thread-5-------37
消費者Thread-2----------37
生產者Thread-0----38
檢測者Thread-4-------38
消費者Thread-3----------38
生產者Thread-1----39
檢測者Thread-5-------39
消費者Thread-2----------39
生產者Thread-0----40
檢測者Thread-4-------40
消費者Thread-3----------40
生產者Thread-1----41
檢測者Thread-5-------41
消費者Thread-2----------41
生產者Thread-0----42
檢測者Thread-4-------42
消費者Thread-3----------42
生產者Thread-1----43
檢測者Thread-5-------43
消費者Thread-2----------43
生產者Thread-0----44
檢測者Thread-4-------44
消費者Thread-3----------44
生產者Thread-1----45
檢測者Thread-5-------45
消費者Thread-2----------45
生產者Thread-0----46
檢測者Thread-4-------46
消費者Thread-3----------46
生產者Thread-1----47
檢測者Thread-5-------47
消費者Thread-2----------47
生產者Thread-0----48
檢測者Thread-4-------48
消費者Thread-3----------48
生產者Thread-1----49
檢測者Thread-5-------49
消費者Thread-2----------49
生產者Thread-0----50
檢測者Thread-4-------50
消費者Thread-3----------50
生產者Thread-1----51
檢測者Thread-5-------51
消費者Thread-2----------51
生產者Thread-0----52
檢測者Thread-4-------52
消費者Thread-3----------52
生產者Thread-1----53
檢測者Thread-5-------53
消費者Thread-2----------53
生產者Thread-0----54
檢測者Thread-4-------54
消費者Thread-3----------54
生產者Thread-1----55
檢測者Thread-5-------55
消費者Thread-2----------55
生產者Thread-0----56
檢測者Thread-4-------56
消費者Thread-3----------56
生產者Thread-1----57
檢測者Thread-5-------57
消費者Thread-2----------57
生產者Thread-0----58
檢測者Thread-4-------58
消費者Thread-3----------58
生產者Thread-1----59
檢測者Thread-5-------59
消費者Thread-2----------59
生產者Thread-0----60
檢測者Thread-4-------60
消費者Thread-3----------60
生產者Thread-1----61
檢測者Thread-5-------61
消費者Thread-2----------61
生產者Thread-0----62
檢測者Thread-4-------62
消費者Thread-3----------62
生產者Thread-1----63
檢測者Thread-5-------63
消費者Thread-2----------63
*/

相關文章