Java中浅谈生产者与消费者问题的演变

  

想要了解更多关于Java生产者消费者问题的演变吗?那就看看这篇文章吧,我们分别用旧方法和新方法来处理这个问题。

  

生产者消费者问题是一个典型的多进程同步问题。

  

对于大多数人来说,这个问题可能是我们在学校,执行第一次并行算法所遇到的第一个同步问题。

  

虽然它很简单,但一直是并行计算中的最大挑战——多个进程共享一个资源。

  

<强>问题陈述
  

  

生产者和消费者两个程序,共享一个大小有限的公共缓冲区。

  

假设一个生产者”生产”一份数据并将其存储在缓冲区中,而一个消费者“消费”这份数据,并将这份数据从缓冲区中删除。

  

再假设现在这两个程序在并发地运行,我们需要确保当缓冲区的数据已满时,生产者不会放置新数据进的来,也要确保当缓冲区的数据为空时,消费者不会试图删除数据缓冲区的数据。

  

<>强解决方案
  

  

为了解决上述的并发问题,生产者和消费者将不得不相互通信。

  

如果缓冲区已满,生产者将处于睡眠状态,直到有通知信息唤醒。

  

在消费者将一些数据从缓冲区删除后,消费者将通知生产者,随后生产者将重新开始填充数据到缓冲区中。

  

如果缓冲区内容为空的化,那么情况是一样的,只不过,消费者会先等待生产者的通知。

  

但如果这种沟通做得不恰当,在进程彼此等待的位置可能导致程序死锁。

  

<强>经典的方法
  

  

首先来看一个典型的Java方案来解决这个问题。

        包ProducerConsumer;      进口java.util.LinkedList;   进口java.util.Queue;      公开课ClassicProducerConsumerExample {      公共静态void main (String [] args)抛出InterruptedException {   缓冲缓冲区=new缓冲区(2);      线程producerThread=新线程(新Runnable () {   @Override   公共空间run () {   尝试{   buffer.produce ();   }捕捉(InterruptedException e) {   e.printStackTrace ();   }   }   });      线程consumerThread=新线程(新Runnable () {   @Override   公共空间run () {   尝试{   buffer.consume ();   }捕捉(InterruptedException e) {   e.printStackTrace ();   }   }   });      producerThread.start ();   consumerThread.start ();      producerThread.join ();   consumerThread.join ();   }      静态类缓冲{      私人Queue列表;   私人int大小;      公共缓冲区大小(int) {   这一点。,列表=new LinkedList<的在();   这一点。大?大小;   }      公共空间产生()抛出InterruptedException {   int值=https://www.yisu.com/zixun/0;   而(真){   同步(){   而(list.size()>=大小){//等待消费者   wait ();   }      list.add(价值);      system . out。println(“生产”+价值);      值+ +;//通知消费者   notify ();      thread . sleep (1000);   }   }   }      公共空间使用()抛出InterruptedException {   而(真){   同步(){   而(list.size ()==0) {//等待生产者   wait ();   }      int value=https://www.yisu.com/zixun/list.poll ();      system . out。println(“消费”+价值);//通知生产商   notify ();      thread . sleep (1000);   }   }   }   }   }      

这里我们有生产者和消费者两个线程,它们共享一个公共缓冲区。生产者线程开始产生新的元素并将它们存储在缓冲区。如果缓冲区已满,那么生产者线程进入睡眠状态,直到有通知唤醒。否,则生产者线程将会在缓冲区创建一个新元素然后通知消费者。就像我之前说的,这个过程也适用于消费者。如果缓冲区为空,那么消费者将等待生产者的通知。否,则消费者将从缓冲区删除一个元素并通知生产者。

  

正如你所看到的,在之前的例子中,生产者和消费者的工作都是管理缓冲区的对象。这些线程仅仅调用了buffer.produce()和buffer.consume()两个方法就搞定了一切。

  

对于缓冲区是否应该负责创建或者删除元素,一直都是一个有争议的话题,但在我看来,缓冲区不应该做这种事情。当然,这取决于你想要达到的目的,但在这种情况下,缓冲区应该只是负责以线程安全的形式存储合并元素,而不是生产新的元素。

  

Java中浅谈生产者与消费者问题的演变