歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Java 多線程讀者寫者問題

Java 多線程讀者寫者問題

  1. /* 
  2.  * 讀者寫者問題 
  3.  *  
  4.  * */  
  5. import java.util.concurrent.locks.*;  
  6. class Buffer   
  7. {  
  8.     public  int  buffer[]=new int [10];//用於標識共享的緩沖區   
  9.     public  boolean flag=false;//用於標識緩沖區的狀態   
  10.     public  int   i;//表示向緩沖區寫的位置    
  11. }  
  12. class Writer implements Runnable //可能會有多個讀   
  13. {  
  14.     private Buffer buffer;  
  15.     public Writer(Buffer buffer)  
  16.     {  
  17.         this.buffer=buffer;  
  18.     }  
  19.     public void run()  
  20.     {  
  21.         while(true)//用循環表示不停地向裡面寫東西   
  22.         {  
  23.             synchronized(buffer)//這裡面是同步代碼塊,裡面都是對共享數據的操作,只能有一個線程操作   
  24.                 {  
  25.                 while(buffer.flag)//如果共享數據flag=true,表示共享數據塊裡面已經寫入數據還沒有被讀出來,如果再寫的話,就要等待,這也是控制讀一次寫一次的關鍵   
  26.                     try{buffer.wait();}catch(Exception ex) {}  
  27.                     buffer.buffer[buffer.i]=buffer.i;//這裡面是向緩沖區裡面寫入數據的操作   
  28.                     buffer.i=((buffer.i+1)%buffer.buffer.length);//防止數據的溢出   
  29.                     buffer.flag=true;  
  30.                     buffer.notifyAll();  
  31.                 }  
  32.             try {Thread.sleep(100);}catch(Exception ex) {}  
  33.     }  
  34.     }  
  35. }  
  36. class Reader implements Runnable  
  37. {  
  38.     private Buffer buffer;  
  39.     public Reader(Buffer buffer)  
  40.     {  
  41.         this. buffer=buffer;  
  42.     }  
  43.     public void run()  
  44.     {  
  45.         while(true//表示 讀者不停在進行讀操作   
  46.         {  
  47.             synchronized(buffer)  
  48.             {  
  49.                 while(!buffer.flag)  
  50.                     try{buffer.wait();}catch(Exception ex) {}  
  51.                     for(int i=0;i<buffer.i;i++)  
  52.                         {  
  53.                             System.out.print(buffer.buffer[i]);  
  54.                         }   
  55.                     System.out.println();  
  56.                     buffer.flag=false;  
  57.                     buffer.notifyAll();  
  58.                       
  59.             }  
  60.             try {Thread.sleep(100);}catch(Exception ex) {}  //這句話沒有什麼意思,只是為了讓輸出會慢一點,在這個程序裡面沒有其他作用,加不加都一個樣   
  61.         }  
  62.     }  
  63. }  
  64. public class ReaderandWriter {  
  65.         public  static void main(String args[])  
  66.         {     
  67.             Buffer buffer=new Buffer();  
  68.             Thread t1=new Thread(new Writer(buffer));  
  69.             Thread t2=new Thread(new Writer(buffer));  
  70.             Thread t3=new Thread(new Reader(buffer));  
  71.             Thread t4=new Thread(new Reader(buffer));  
  72.             t1.start();  
  73.             //t2.start();   
  74.             t3.start();  
  75.             t4.start();  
  76.               
  77.               
  78.         }  
  79. }  
  80. /* 
  81.  *              上面的程序在只有一個讀者和一個寫者的情況 下沒有任何錯誤,寫者沒寫進一個數據,讀者就讀取數據一次 
  82.  *  而在實際中,線程的個數可能會有很多種,在有多個讀者和多個寫者的情況下,上面的代碼又會現在一個新的問題--- 
  83.  *              那就是在寫一個而讀多次,或者是讀一次而寫多次,這將會出現安全性問題,下面我們討論一下為什麼出現這種問題 
  84.  *        假設現在有兩個讀者和兩個寫者,現在執行的線程是讀者,兩個寫者wait 中,讀者執行完後喚醒其中的一個寫者,然後寫者開始執行 
  85.  *          當寫者執行完成後,下面又開始要喚醒線程,因為上面的兩個讀線程和一個寫線程都在等待當中,如果喚醒的是再是寫線程,因為裡面用的是 
  86.  *          if(buffer.flag) 這個在wait 之前就已經判斷過了,所以會直接執行下面的語句,那麼就是在讀了一次的情況下,而連接寫了兩次,如果寫的線程更多 的話, 
  87.  *          那麼就會出現更多 的問題,所以上面的if(buffer.flag)要改成while(buufer.flag) buffer.notify 要改成buffer.notifyAll();這樣就正確了 
  88.  *       
  89.  *       
  90.  *      上面的程序由於由whiie(flag) notifyAll  控制,所以,無論 寫者線程或讀者線程有多少個,無論是否相同,它們都將遵守讀一個寫一個的順序了 
  91.  *                       
  92.  *                                                                                                  2011/10/24  19:21:45 
  93.  *  
  94.  *  
  95.  * */  
Copyright © Linux教程網 All Rights Reserved