java多線程通信之二等待/喚醒機制

/**
  * 多線程之間的通信2---等待/喚醒機制
  *   
  *  分析: 爲啥要用等待/喚醒機制呢?
  *   
  *   簡單來講嘛  個人多線線程通信之一代碼輸出後的結果:Look 我中間複製的
        Thread-1賣出了..penicillin -青黴素--品種--penicillin -西藥=
        Thread-1賣出了..penicillin -青黴素--品種--penicillin -西藥=
        Thread-1賣出了..penicillin -青黴素--品種--penicillin -西藥=
        Thread-1賣出了..penicillin -青黴素--品種--penicillin -西藥=
        Thread-1賣出了..penicillin -青黴素--品種--penicillin -西藥=
        Thread-0我進口了..雲南白藥--品種--中藥
        Thread-0我進口了..penicillin -青黴素--品種--penicillin -西藥
        Thread-0我進口了..雲南白藥--品種--中藥
        Thread-0我進口了..penicillin -青黴素--品種--penicillin -西藥
        Thread-0我進口了..雲南白藥--品種--中藥
        Thread-0我進口了..penicillin -青黴素--品種--penicillin -西藥
       .......
  *
  *     問題?:我們來看一下這個結構是否是有點問題,是否是合理呢?
  *                看觀們都跳出一實現生活哈,我開始舉例有點不恰當
  *
  *     這個樣子
  *     咱們能夠不能夠這樣想問題呢,不要想複雜了,就這麼來
  *
  *      好比進口一個藥品,再買一個藥品,那麼輸出的結構是應該是這個樣子的
         Thread-0我進口了..penicillin -青黴素--品種--penicillin -西藥 ===》進口
         Thread-1賣出了..penicillin -青黴素--品種--penicillin -西藥= ===>賣出
         Thread-0我進口了..雲南白藥--品種--中藥===》進口
  *     Thread-1賣出了..penicillin -雲南白藥--品種--penicillin -中藥= ===>賣出
         Thread-0我進口了..penicillin -青黴素--品種--penicillin -西藥 ===》進口
         Thread-1賣出了..penicillin -青黴素--品種--penicillin -西藥= ===>賣出
         Thread-0我進口了..雲南白藥--品種--中藥===》進口
  *     Thread-1賣出了..penicillin -雲南白藥--品種--penicillin -中藥= ===>賣出
  *     對就這個結構
  *
  *     簡單來講,我想造成這樣一個買賣結構那麼這樣怎麼作,在多線程通信的時候
  *
  *     這樣就用到了 等待/喚醒機制,其實啊,核心原理其實和同步鎖有些類同,是類同,不是就是,
  *
  *     實現這一功能, java怎麼作
  *     涉及的方法是 
  *     1.wait(); 讓線程處於凍結狀態,被wait的線程會被存儲到線程池中
  *     2.notify(); 喚醒線程池中一個線程(或者任意)
  *     3.notifyAll();喚醒線程池中全部線程
  *        sleep()也能夠中斷異常
  *     可是上面的方法有前提條件,必須定義在同步代碼塊或者同步函數中
  *       簡單解釋一下,不是很標準,可是很好理解
  *
  *      上面方法是判斷線程的一個狀態,那麼確定是判斷那個資源(就是共同執行對象)的單個線程的狀態的嘛
  *      可是問題是我作的是多線程編程的嘛,怎麼能在保證在同一時刻保證判斷的是一個並且還能明確操做的對象呢?
  *      java中不就是隻有同步嘛, 註釋:這是我的言論,不對望見諒,其實這個說確實有點怪,
  *          
  *      閒聊一下,java 中涉及的監視器就是這個同步鎖,這麼來看,java中全部對象都繼承了object嘛,
  *     簡單來講 上面幾個方法都Object的內方法而已
  *
  *    對於 PHPer們
  *     PHP面向對象,
  *    當對於對象序列化時候有一個睡眠魔術方法__sleep
  *    當對象被反序列化時候有一個喚醒的魔術方法__wakeup 
  *
  *     這兩個魔術方法某一種程度有相似型,只是相似性哈 
  *     固然這種說法,是我我的說的,本人才疏學淺,說的不對處還望見諒,
  *    主要PHP沒有多線程,無法比喻,要想本身記得深入點,還真要找一個東西對照一下
       php 也有sleep函數哈,java線程也有哈
  *    
  **/


//藥品資源
class  DrugResource
{
       String  DrugName;  /*藥品名字*/
       String  Drugtype;    /*西藥or中藥*/
       boolean  falg =false;        /**主要好判斷何時該等待|什麼該喚醒*/ 
}

/**進口藥品*/
class  ImportDrugs  implements  Runnable
{             
          DrugResource d;//藥品資源對象,保證,兩個任務操做同一個對象  

          ImportDrugs(DrugResource  d){
          
                this.d = d;
          }

            
          public    void  run() { /**線程入口程序*/
              
                 imports();
          }

                           /**線程真正要執行代碼塊**/
          public   void  imports() {
                      int  x = 0 ;
                    
                     while(true) 
                     {    
                            //若是不對wait捕獲異常下面代碼捕獲異常會出現
                         /**
                            *
                            * ThreadResourceTwo.java:97: 未報告的異常 java.lang.InterruptedException;必須對其進行捕捉或聲明以便拋出
                                                         if(d.falg)      d.wait();
                                                                                ^
                            *  下一個任務也同理
                            *
                            ****/
                            //若是等於ture 那麼就說我如今就藥品了是把,直接凍結
                            //若是false 就說明沒有貨了嘛,就直接往下走澀,說白了嘛,就去進口藥品嘛
                             if(d.falg)    
                             try{d.wait();}catch(InterruptedException e){} //這裏簡單處理
                        
                                                                
                             synchronized(d){  //同步鎖也是同步代碼塊 前提是公用一個對象  d就是一個公用對象 
                                         
                                 
                                 
                                     if(x==0)    //來回切換這個if--sele 取模運算給我線程沒啥關係只是讓他來顯示看見的效果比較好
                                      {    
                                            d.DrugName = "penicillin -青黴素";
                                            d.Drugtype = "penicillin -西藥";

                                        
                                      } else {
                                            
                                             
                    
                                            d.DrugName = "雲南白藥";
                                             d.Drugtype = "中藥";
                                        
                                         
                                      }
                                      System.out.println(Thread.currentThread().getName()+"進口了.."+d.DrugName+"--品種--"+d.Drugtype);
                                       //注意上面運行完了,是說,我如今已經進口一個藥品了啊,
                                       d.falg = true;     //立刻重置爲ture; 說了的意思,我有已經有貨了
                                       d.notify() ;  //我就喚醒賣的線程了嘛,說白了,就是,哥們我這進了貨了,你能夠去賣了
                                      x = (x+1)%2;  

                                        //解釋 x = (x+1)%2;  
                                        /**
                                         *  x =0時候
                                         *  (0+1)%2
                                         *   1%2 = 1
                                         *
                                         *    x=1;
                                         *  (1+1)%2 = 2%2 = 0
                                         *
                                         *  這樣就能切換了
                                         *  這個東西沒意義,可是仍是解釋一下
                                         */
                                   }
                                 
                             }
                 
                  
         
            }

}


/**賣藥品*/
class  SellDrugs  implements  Runnable
{
          
          DrugResource d ;  //藥品資源對象,保證,兩個任務操做同一個對象

          SellDrugs(DrugResource  d){
          
                this.d = d;
          }

          public    void  run() {  /**線程入口程序*/
                  sell();
          }
                  /**線程真正要執行代碼塊**/
          public  void   sell(){
            
              
                while(true) 
                 {           

                       synchronized(d){
                                //Thread.currentThread().getName()  取出當前運行中進程名
                               //若是 false 說明沒貨,!取反那就爲真,就等待那哥們進貨嘛
                               //若是 ture  !取反 那是否是就爲假嘛, 那我就明白了,有貨了,就執行下面的話
                               if(!d.falg) try{d.wait();}catch(InterruptedException e){} //這裏簡單處理 
                               
                                  
                              
                             System.out.println(Thread.currentThread().getName()+"賣出了.."+d.DrugName+"--品種--"+d.Drugtype);
                              


                               //買完以後是否是應該作一步動做呢,我都賣出了,那還有麼?確定沒了嘛重置
                               d.falg = false;  //
                              d.notify(); //而後呢?確定是喚醒負責進口的這個線程嘛,意思是,哥們我賣完了,你應該進貨了

                      }
                 }
            
          }

}


class   TreadResourceTwo
{

            public   static  void  main(String[]  args) {
                       

                   DrugResource d = new  DrugResource(); //資源對象

                   ImportDrugs  work1 = new ImportDrugs(d) ; //任務對象一 進口任務

                   SellDrugs  work2 = new SellDrugs(d) ; //任務對象二  賣任務

 
                   
                   /*********執行路徑********/

                    Thread   t1 = new Thread(work1);
                    Thread   t2 = new Thread(work2);

                    t1.start();  //開啓線程
                    t2.start(); //開啓線程
            }          
}

  代碼整理一下php

//藥品資源
class  DrugResource
{
       private String  DrugName;  /*藥品名字*/
       private String  Drugtype;    /*西藥or中藥*/
       private boolean  falg =false;        /**主要好判斷何時該等待|什麼該喚醒*/ 

         /****進口的***/
       public synchronized  void  set(String DrugName,String Drugtype) {//加入了同步函數
              
              if(this.falg)  //我喜歡加this明確點,本人搞PHP搞習慣了
                 try{this.wait();}catch(InterruptedException e){}
                 this.DrugName = DrugName;
                 this.Drugtype =Drugtype;
 System.out.println(Thread.currentThread().getName()+"--進口了的----"+this.DrugName+"-----++---"+this.Drugtype);
                 this.falg =true;
                 this.notify() ;
       }  
       /***賣出的**/
       public synchronized   void  out() { //加入了同步函數
          if(!this.falg)
             try{this.wait();}catch(InterruptedException e){}
             System.out.println(Thread.currentThread().getName()+"----賣出的----"+this.DrugName+"-----++---"+this.Drugtype);
             this.falg =false;
             this.notify() ;
       }

}


/**進口藥品*/
class  ImportDrugs  implements  Runnable
{             
          DrugResource d;//藥品資源對象,保證,兩個任務操做同一個對象  

          ImportDrugs(DrugResource  d){
          
                this.d = d;
          }

            
          public    void  run() { /**線程入口程序*/
              
                 imports();
          }

                           /**線程真正要執行代碼塊**/
          public   void  imports() {
                       int  x = 0 ;
                       while(true)     
                       {
                             if (x==0)
                             {
                                   d.set("penicillin -青黴素","penicillin -西藥");
                              }else {
                                   d.set("雲南白藥","中藥");
                             }
                             x = (x+1)%2;
                       }
           }
}


/**賣藥品*/
class  SellDrugs  implements  Runnable
{
          
          DrugResource d ;  //藥品資源對象,保證,兩個任務操做同一個對象

          SellDrugs(DrugResource  d){
          
                this.d = d;
          }

          public    void  run() {  /**線程入口程序*/
                  sell();
          }
                  /**線程真正要執行代碼塊**/
          public  void   sell(){              
                while(true) 
                 {           
                    d.out();
                 }
          }

}


class   TreadResourceTwo
{

            public   static  void  main(String[]  args) {
                       

                   DrugResource d = new  DrugResource(); //資源對象

                   ImportDrugs  work1 = new ImportDrugs(d) ; //任務對象一 進口任務

                   SellDrugs  work2 = new SellDrugs(d) ; //任務對象二  賣任務

 
                   
                   /*********執行路徑********/

                    Thread   t1 = new Thread(work1);
                    Thread   t2 = new Thread(work2);

                    t1.start();  //開啓線程
                    t2.start(); //開啓線程
            }          
}
相關文章
相關標籤/搜索