天天看點

java多線程的同步 通信以及生産消費者問題

Demo1

/*   Runable接口比直接從Thread繼承友善的多  。 

*    new  Thread(...) ;這樣即使我們傳遞了同一個實作了Runnable接口的多個對象那麼 也是多個線程 ,而且多個線程共享資料域.

*    否則new Thread 建立的多個線程之間 互不相幹  ,資料之間互不幹涉

*    同步就是為了實作 在多個線程同時對一個資源進行操作的時候 要一個一個的執行 ,

*    隻有等占有CPU的 線程完事之後 其他等待線程才能進入就緒狀态等待運作

*    java中可以用 synchrozined(Object obj){}      實作代碼塊的同步      參數是任意對象 

*    不但可以利用synchronized語句塊  也可以在方法的前面 聲明 synchronized      

*    同步原理是對象的标志位 初始為1  當進入代碼塊後 obj的标志位變為 0  這時候其他線程則不能 進入代碼塊執行 而進入等待狀态

*    直到先進入的那個線程完事然後就會為這個線程解鎖 。 其他線程才可能開始運作   火車票的售票系統就是一個多線程很好的運用的例子

*    同步是以程式的性能為代價的   ,同步方法是以類的this對象為同步對象的  而 synchronized塊是以我們指定的對象為 同步對象

*    如果想讓代碼塊和同步方法同步那麼 使用的同步對象 必須都為this

*/  

public class  ThreadDemo2

{

   public static void main(String []args)

   {

       MyThread mt=new MyThread() ;  

       //mt.start() ;

       new Thread(mt) .start() ;

       try

      {

       Thread.sleep(10) ; //每當産生一個線程CPU不會立馬去執行 ,這之間既有一個微小的時間間隔 。

      }

      catch(Exception e)

       System.out.println(e.toString()) ;

       mt.str="method";

   }

}

class  MyThread    implements Runnable// extends   Thread

{  

   int tickets=100 ;

   String str=new String("");

   public void run()

       if(str.equals("method"))

       {

        while(true)

        {

         running() ;

        }

       }

       else

         synchronized(str)

         if(tickets>0 )

         {

          System.out.println("block:"+Thread.currentThread().getName()+"sells"+tickets--);

         }

   public  synchronized  void running()

   {    

      if(tickets>0) 

       {

        try{Thread.sleep(10);}catch(Exception ex){}

        System.out.print("method:") ;

        System.out.println(Thread.currentThread() +"sell " + tickets-- ) ;

       }

}  

Demo2:

/*

*   java多線程中 有前台線程和背景線程,前台線程 是指 main所在的主線程 和其他 建立的線程 ,如果線上程調用start 之前調用  setDeamon(true)

*   那麼 這個線程就是一個背景線程,在程序中如果沒有一個前台線程 那麼背景線程也随之退出,進而程序也退出 。如果沒有調用setDeamon(true)或者

*   調用setDeamom(false)那麼這個線程就是前台線程 ,隻要一個程序中還存在前台線程 那麼即使mian方法所在的線程退出了 ,那麼這個前台子線程也會繼續執行

*   直至退出  。

*   Tread類額join方法 是将一個線程合并到另一個線程中, 可以設定合并的時間間隔

*   我們實作自己的線程類有2中方法  :

*   1、直接從Thread繼承而來  實作 run方法  。

*   2、實作Runnable接口,并且實作run方法 。 Thread  th=new Thread(....) ;//吧我們自己實作的類的對象作為參數傳進去   .

*   join 方法可以将一個線程合并到另一個線程 中 而且還可以指定線程合并的時間間隔

*

*/

public  class  ThreadDemo1

      public static  void main(String[]args) 

      {

        //MyThread tt=new MyThread() ; tt.start() ;可以從 Thread類派生一個線程類

        Thread tt=new Thread(new MyThread()) ;  //可以通過Thread類的帶參數的構造方法 傳遞一個實作了Runnable接口的對象

   //     tt.setDaemon(true) ;//将線程設定為 背景線程  主線層退出這個線程也會随着退出 

        tt.start() ;

        int index=0 ;

        while(true)

        {

         if(index++==100)

         try{

           tt.join(5000) ;

         }

         catch(Exception ex)

         System.out.println(ex.toString()) ;

        }

         System.out.println("run:"+Thread.currentThread().getName()) ;

      }

class  MyThread  implements Runnable//extends    Thread

    public void run()

    {

      while(true)

      System.out.println("run:"+Thread.currentThread().getName()) ;

    }

Demo3:

/*   線程之間的通信是協調線程同步的重要方法   、

*    Object類的 wait方法通告同步對象進入等待狀态,直到其他線程得到同步對象 并且調用 notity方法 ,等待線程才會繼續執行

*    notify方法 是通告同步對象的等待線程進入恢複運作 

*    notifyAll通告所有堵塞線程恢複運作

*     下面是一個生産消費者的問題   ,在對于類的操作的時候 一定要有面向對象的思想  。  否則 就會非常的雜亂

class  Producer  implements  Runnable

 Q q  ;

 public Producer(Q q)

 {

  this.q=q ;

 }

 public  void run()

 { 

    int i=0 ;

    while(true)

    /* synchronized(q)

     {

      if(q.bFull==true)

          try{q.wait() ;}catch(Exception ex){}

         if(i==0)

       q.name="zhangsan" ;

       try{

       Thread.sleep(1) ;

      }catch(Exception ex){}

       q.sex="male"  ;

     }

     else

      q.name="lisi"  ;

      q.sex="female" ;

     }  

     q.bFull=true ;

     q.notify() ;

     i=(i+1)%2 ;

     */ 

     if(i==0 )

      q.push("zhangsan","male");

       else

      q.push("lisi","female") ;  

      i=(i+1)%2 ;

class Consumer implements  Runnable 

   Q q ;

   public Consumer(Q q)

    this.q=q ;

   public   void  run()

      while(true)

     {

     /*  synchronized(q)

       {

         if(!q.bFull)

         {

        try{q.wait() ;}catch(Exception ex){}

          }

          System.out.println(q.name+":"+q.sex) ;

          q.bFull=false ;

           q.notify() ;

        }

      */

      q.get() ;

     }

class  Q   //以面向對象的思想對線程之間的通信進行封裝進而實作消費者 生産社的問題

 String name="unknown"  ;

 String sex ="unknown"  ;

 boolean bFull=false ;

 public synchronized void push(String name,String sex)

 {     

      if(this.bFull==true)

               try{wait() ;}catch(Exception ex){}

       this.name=name ;

       this.sex=sex   ; 

       bFull=true ;

       try{notify() ;}catch(Exception ex){}

 public synchronized void get()

  if(this.bFull==false)

     try{wait() ;}catch(Exception ex){}

  System.out.println("name:"+this.name+" sex:"+this.sex) ;

     bFull=false ;

     try{notify() ;}catch(Exception ex){}

class  ThreadTest  implements  Runnable    //這個線程類 來模拟線程的聲明結束  因為Thread類的 stop suspend等方法都已經過時了

{                                          //是以有時候我們對于線程的開始和結束要自己設定标志位來

  boolean bRun=true ;

  int index=0 ;

  public  void  stopMe()

  {

   bRun=false ;

  }

  public  void run()

   while(bRun)

   { 

      if(++index>100)

        stopMe() ;

     System.out.println(Thread.currentThread().getName()+" is running!");

   }

public  class  ThreadDemo3

   public static void main(String[]args)

   Q q=new Q() ;

    new Thread(new Producer(q)).start() ;

   new Thread(new Consumer(q)).start() ;