Java中生产者-消费者关系程序的输出不一致
我编写了一段代码来查看Java中的生产者-消费者关系,如下所示。 虽然程序运行良好,但我发现输出中存在不一致。 有人能说明以下不一致的原因吗Java中生产者-消费者关系程序的输出不一致,java,multithreading,Java,Multithreading,我编写了一段代码来查看Java中的生产者-消费者关系,如下所示。 虽然程序运行良好,但我发现输出中存在不一致。 有人能说明以下不一致的原因吗 class ProdCons2 { public static void main (String [] args) { Shared s = new Shared (); new Producer (s).start (); new Consumer (s).start (); } } class
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');
}
}
观察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.
不要编写
wait()/notify()
使用JDK中的标准并发类:BlockingQueue
接口非常适合多线程环境中的消费者/生产者。不要编写wait()/notify())
使用JDK中的标准Concurence类:BlockingQueue
接口非常适合多线程环境中的使用者/生产者。日志记录语句不属于同步部分。所以完全有可能发生这样一系列事件:
- 生产者生产P,疏通消费者
- 消费者消耗P,解除生产者阻塞
- 生产商记录P生产
- 生产商生产Q,疏通消费者
- 生产商记录Q生产
- 消费者日志P消费
- 消费者消费Q
- 消费者日志Q消费
如果您希望总是在生产结束后立即记录消耗量,那么日志记录语句应该位于代码的同步部分。日志记录语句不属于同步部分。所以完全有可能发生这样一系列事件:
- 生产者生产P,疏通消费者
- 消费者消耗P,解除生产者阻塞
- 生产商记录P生产
- 生产商生产Q,疏通消费者
- 生产商记录Q生产
- 消费者日志P消费
- 消费者消费Q
- 消费者日志Q消费
如果您希望总是在生产结束后立即记录消耗量,那么日志记录语句应该在代码的同步部分内。尽管输出不一致,但并不是不正确的。我认为System.out.println()没有放在正确的位置。调用ch=s.getSharedChar()时,ch接收值P,并立即调用下面的s.setSharedChar(ch)和System.out.println()语句,并打印生产者生成的Q。之后,消费者消耗的P将按照消费者线程的get方法打印。虽然输出不一致,但并没有错误。我认为System.out.println()没有放在正确的位置。调用ch=s.getSharedChar()时,ch接收值P,并立即调用下面的s.setSharedChar(ch)和System.out.println()语句,并打印生产者生成的Q。然后,按照消费线程的get方法打印消费线程消耗的P。
P produced by producer.
P consumed by consumer.
Q produced by producer.
Q consumed by consumer.