Java 实例 - 生产者/消费者问题


生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一个存储空间,如下图所示,生产者向空间里存放数据,而消费者取用数据,如果不加以协调可能会出现以下情况:

存储空间已满,而生产者占用着它,消费者等着生产者让出空间从而去除产品,生产者等着消费者消费产品,从而向空间中添加产品。互相等待,从而发生死锁。

Java 实例 - 生产者/消费者问题

以下实例演示了如何通过线程解决生产者/消费者问题:

  1. /*
  2. author by shouce.ren
  3. ProducerConsumerTest.java
  4. */
  5.  
  6. public class ProducerConsumerTest {
  7. public static void main(String[] args) {
  8. CubbyHole c = new CubbyHole();
  9. Producer p1 = new Producer(c, 1);
  10. Consumer c1 = new Consumer(c, 1);
  11. p1.start();
  12. c1.start();
  13. }
  14. }
  15. class CubbyHole {
  16. private int contents;
  17. private boolean available = false;
  18. public synchronized int get() {
  19. while (available == false) {
  20. try {
  21. wait();
  22. }
  23. catch (InterruptedException e) {
  24. }
  25. }
  26. available = false;
  27. notifyAll();
  28. return contents;
  29. }
  30. public synchronized void put(int value) {
  31. while (available == true) {
  32. try {
  33. wait();
  34. }
  35. catch (InterruptedException e) {
  36. }
  37. }
  38. contents = value;
  39. available = true;
  40. notifyAll();
  41. }
  42. }
  43.  
  44. class Consumer extends Thread {
  45. private CubbyHole cubbyhole;
  46. private int number;
  47. public Consumer(CubbyHole c, int number) {
  48. cubbyhole = c;
  49. this.number = number;
  50. }
  51. public void run() {
  52. int value = 0;
  53. for (int i = 0; i < 10; i++) {
  54. value = cubbyhole.get();
  55. System.out.println("消费者 #" + this.number+ " got: " + value);
  56. }
  57. }
  58. }
  59.  
  60. class Producer extends Thread {
  61. private CubbyHole cubbyhole;
  62. private int number;
  63.  
  64. public Producer(CubbyHole c, int number) {
  65. cubbyhole = c;
  66. this.number = number;
  67. }
  68.  
  69. public void run() {
  70. for (int i = 0; i < 10; i++) {
  71. cubbyhole.put(i);
  72. System.out.println("生产者 #" + this.number + " put: " + i);
  73. try {
  74. sleep((int)(Math.random() * 100));
  75. } catch (InterruptedException e) { }
  76. }
  77. }
  78. }

以上代码运行输出结果为:

  1. 消费者 #1 got: 0
  2. 生产者 #1 put: 0
  3. 生产者 #1 put: 1
  4. 消费者 #1 got: 1
  5. 生产者 #1 put: 2
  6. 消费者 #1 got: 2
  7. 生产者 #1 put: 3
  8. 消费者 #1 got: 3
  9. 生产者 #1 put: 4
  10. 消费者 #1 got: 4
  11. 生产者 #1 put: 5
  12. 消费者 #1 got: 5
  13. 生产者 #1 put: 6
  14. 消费者 #1 got: 6
  15. 生产者 #1 put: 7
  16. 消费者 #1 got: 7
  17. 生产者 #1 put: 8
  18. 消费者 #1 got: 8
  19. 生产者 #1 put: 9
  20. 消费者 #1 got: 9