Java中生产者消费者关系计划的输出不一致

我编写了一个代码来查看Java中的Producer Consumer关系,如下所示。 虽然程序工作正常但我看到输出不一致。 有人可以说明以下不一致的原因。

class ProdCons2 { public static void main (String [] args) { Shared s = new Shared (); new Producer (s).start (); new Consumer (s).start (); } } class Shared { private char c = '\u0000'; private boolean writeable = true; synchronized void setSharedChar (char c) { while (!writeable) try { wait (); } catch (InterruptedException e) {} this.c = c; writeable = false; notify (); } synchronized char getSharedChar () { while (writeable) try { wait (); } catch (InterruptedException e) { } writeable = true; notify (); return c; } } class Producer extends Thread { private Shared s; Producer (Shared s) { this.s = s; } public void run () { for (char ch = 'A'; ch <= 'Z'; ch++) { try { Thread.sleep ((int) (Math.random () * 1000)); } catch (InterruptedException e) {} s.setSharedChar (ch); System.out.println (ch + " produced by producer."); } } } class Consumer extends Thread { private Shared s; Consumer (Shared s) { this.s = s; } public void run () { char ch; do { try { Thread.sleep ((int) (Math.random () * 1000)); } catch (InterruptedException e) {} ch = s.getSharedChar (); System.out.println (ch + " consumed by consumer."); } while (ch != 'Z'); } } 

它给了我如下输出:

  A produced by producer. A consumed by consumer. B produced by producer. B consumed by consumer. C produced by producer. C consumed by consumer. D produced by producer. D consumed by consumer. E produced by producer. F produced by producer. E consumed by consumer. F consumed by consumer. G produced by producer. G consumed by consumer. H produced by producer. I produced by producer. H consumed by consumer. I consumed by consumer. J produced by producer. J consumed by consumer. K produced by producer. L produced by producer. K consumed by consumer. L consumed by consumer. M produced by producer. M consumed by consumer. N produced by producer. N consumed by consumer. O produced by producer. O consumed by consumer. P produced by producer. Q produced by producer. P consumed by consumer. Q consumed by consumer. R produced by producer. R consumed by consumer. S produced by producer. S consumed by consumer. T produced by producer. T consumed by consumer. U produced by producer. U consumed by consumer. V produced by producer. V consumed by consumer. W consumed by consumer. W produced by producer. X produced by producer. X consumed by consumer. Y consumed by consumer. Y produced by producer. Z produced by producer. Z consumed by consumer. 

观察P和Q处的输出:

 P produced by producer. Q produced by producer. P consumed by consumer. Q consumed by consumer. 

控制台不打印的原因是什么:

 P produced by producer. P consumed by consumer. Q produced by producer. Q consumed by consumer. 

日志记录语句不是同步部分的一部分。 因此,完成这一系列事件是完全可能的:

  • 生产者生产P,解锁消费者
  • 消费者消费P,解锁生产者
  • 生产者记录P生产
  • 生产者生产Q,解锁消费者
  • 生产者记录Q生产
  • 消费者记录消费量
  • 消费者消费Q.
  • 消费者记录Q消费

它产生你观察到的输出。

如果您希望在生产之后始终记录消耗,那么日志记录语句应该在代码的同步部分内。

而不是编写wait() / notify()而不是使用JDK的标准concurency类: BlockingQueue接口非常适合multithreading环境中的Consumer / Producer。