Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中生产者-消费者关系程序的输出不一致_Java_Multithreading - Fatal编程技术网

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

我编写了一段代码来查看Java中的生产者-消费者关系,如下所示。 虽然程序运行良好,但我发现输出中存在不一致。 有人能说明以下不一致的原因吗

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.