歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Java 多線程讀者寫者問題

Java 多線程讀者寫者問題

日期:2017/3/1 11:09:37   编辑:Linux編程

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. try {Thread.sleep(100);}catch(Exception ex) {} //這句話沒有什麼意思,只是為了讓輸出會慢一點,在這個程序裡面沒有其他作用,加不加都一個樣
  60. }
  61. }
  62. }
  63. public class ReaderandWriter {
  64. public static void main(String args[])
  65. {
  66. Buffer buffer=new Buffer();
  67. Thread t1=new Thread(new Writer(buffer));
  68. Thread t2=new Thread(new Writer(buffer));
  69. Thread t3=new Thread(new Reader(buffer));
  70. Thread t4=new Thread(new Reader(buffer));
  71. t1.start();
  72. //t2.start();
  73. t3.start();
  74. t4.start();
  75. }
  76. }
  77. /*
  78. * 上面的程序在只有一個讀者和一個寫者的情況 下沒有任何錯誤,寫者沒寫進一個數據,讀者就讀取數據一次
  79. * 而在實際中,線程的個數可能會有很多種,在有多個讀者和多個寫者的情況下,上面的代碼又會現在一個新的問題---
  80. * 那就是在寫一個而讀多次,或者是讀一次而寫多次,這將會出現安全性問題,下面我們討論一下為什麼出現這種問題
  81. * 假設現在有兩個讀者和兩個寫者,現在執行的線程是讀者,兩個寫者wait 中,讀者執行完後喚醒其中的一個寫者,然後寫者開始執行
  82. * 當寫者執行完成後,下面又開始要喚醒線程,因為上面的兩個讀線程和一個寫線程都在等待當中,如果喚醒的是再是寫線程,因為裡面用的是
  83. * if(buffer.flag) 這個在wait 之前就已經判斷過了,所以會直接執行下面的語句,那麼就是在讀了一次的情況下,而連接寫了兩次,如果寫的線程更多 的話,
  84. * 那麼就會出現更多 的問題,所以上面的if(buffer.flag)要改成while(buufer.flag) buffer.notify 要改成buffer.notifyAll();這樣就正確了
  85. *
  86. *
  87. * 上面的程序由於由whiie(flag) notifyAll 控制,所以,無論 寫者線程或讀者線程有多少個,無論是否相同,它們都將遵守讀一個寫一個的順序了
  88. *
  89. * 2011/10/24 19:21:45
  90. *
  91. *
  92. * */
Copyright © Linux教程網 All Rights Reserved