java Java中使用wait()和notify()的生产者消费者程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27591043/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Producer Consumer Program using wait() and notify() in Java
提问by Anurag
I am doing classic Producer-Consumer problem in Java using low level synchronization and wait() and notify(). I know there are better implementations using structures from java.util.concurrent package but my problem revolves around low level implementation:
我正在使用低级同步和wait() 和notify() 在Java 中做经典的生产者-消费者问题。我知道使用 java.util.concurrent 包中的结构有更好的实现,但我的问题围绕低级实现:
private static ArrayList<Integer> list = new ArrayList<Integer>();
static Object obj = new Object();
public static void producer() throws InterruptedException {
synchronized (obj) {
while (true) {
if (list.size() == 10) {
System.out.println("Queue full.. Waiting to Add");
obj.wait();
} else {
int value = new Random().nextInt(100);
if (value <= 10) {
Thread.sleep(200);
System.out.println("The element added was : " + value);
list.add(value);
obj.notify();
}
}
}
}
}
public static void consumer() throws InterruptedException {
synchronized (obj) {
while (true) {
Thread.sleep(500);
if (list.size() == 0) {
System.out.println("Queue is empty...Waiting to remove");
obj.wait();
} else {
System.out.println("The element removed was : "
+ list.remove(0));
obj.notify();
}
}
}
}
There are 2 threads in the program, 1 each for producer and consumer specifically. The code works just fine.
程序中有 2 个线程,生产者和消费者各 1 个。代码工作得很好。
The only issueis that producer goes on to produce messages until the maximum at once (until size is 10 for the list), and consumer consumes all 10 at once.
唯一的问题是生产者继续生产消息直到最大一次(直到列表的大小为 10),而消费者一次消费所有 10。
How can I make producer and consumer work at the same time?
如何让生产者和消费者同时工作?
This is the sample output:
这是示例输出:
The element added was : 4
The element added was : 0
The element added was : 0
The element added was : 4
The element added was : 3
The element added was : 1
The element added was : 10
The element added was : 10
The element added was : 3
The element added was : 9
Queue full.. Waiting to Add
The element removed was : 4
The element removed was : 0
The element removed was : 0
The element removed was : 4
The element removed was : 3
The element removed was : 1
The element removed was : 10
The element removed was : 10
The element removed was : 3
The element removed was : 9
Queue is empty...Waiting to remove
Edit:Here is the corrected code:
编辑:这是更正后的代码:
private static ArrayList<Integer> list = new ArrayList<Integer>();
private static Object obj = new Object();
public static void producer() throws InterruptedException {
while (true) {
Thread.sleep(500);
if (list.size() == 10) {
System.out.println("Waiting to add");
synchronized (obj) {
obj.wait();
}
}
synchronized (obj) {
int value = new Random().nextInt(10);
list.add(value);
System.out.println("Added to list: " + value);
obj.notify();
}
}
}
public static void consumer() throws InterruptedException {
while (true) {
Thread.sleep(500);
if (list.size() == 0) {
System.out.println("Waiting to remove");
synchronized (obj) {
obj.wait();
}
}
synchronized (obj) {
int removed = list.remove(0);
System.out.println("Removed from list: " + removed);
obj.notify();
}
}
}
回答by Ali Sepehri.Kh
You can not run two thread in synchronized block with same object. When one method is running another method can not run until another thread call wait
method.
您不能在具有相同对象的同步块中运行两个线程。当一个方法正在运行时,另一个方法不能运行,直到另一个线程调用wait
方法。
To solve this problem you should just put add
and remove
in synchronized block. For more information see this.
要解决此问题,您应该只放入add
和remove
同步块。有关更多信息,请参阅此。
回答by Bhupendra Singh
Producer and Consumer problem is the classic example of multiple-process synchronization problem. This describes two process, producer and consumer which share the common resources, buffer. Producer job is to generate data and put it into a buffer and consumer job is consume the generated data and remove from the buffer.
生产者和消费者问题是多进程同步问题的经典例子。这描述了共享公共资源缓冲区的两个进程,生产者和消费者。生产者工作是生成数据并将其放入缓冲区,消费者工作是消费生成的数据并从缓冲区中删除。
Producer must ensure that no element should be added when buffer is full, it should call wait()
until consumer consume some data and notify
to the producer thread AND consumer must ensure that it should not try to remove item from buffer when it is already empty, it should call wait()
which simply waits until producer generate data and add it into buffer and notify to the consumer using notify
or notifyAll
.
生产者必须确保当缓冲区已满时不应添加任何元素,它应该调用wait()
直到消费者消费一些数据并notify
到生产者线程并且消费者必须确保它不应该在缓冲区已经空时尝试从缓冲区中删除项目,它应该调用wait()
它只是等待生产者生成数据并将其添加到缓冲区并使用notify
or通知消费者notifyAll
。
This problem can be solved using BlockingQueue
interface which do manage this producer and consumer implementation own.
这个问题可以使用BlockingQueue
管理这个生产者和消费者实现自己的接口来解决。
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/*
* To change this license header, choose License Headers in Project `Properties`.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* @author sakshi
*/
public class ThreadProducer {
static List<Integer> list = new ArrayList<Integer>();
static class Producer implements Runnable {
List<Integer> list;
public Producer(List<Integer> list) {
this.list = list;
}
@Override
public void run() {
synchronized (list) {
for (int i = 0; i < 10; i++) {
if (list.size() >= 1) {
try {
System.out.println("producer is waiting ");
list.wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.println("produce=" + i);
list.add(i);
list.notifyAll();
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
//To change body of generated methods, choose Tools | Templates.
}
}
static class Consumer implements Runnable {
List<Integer> list;
public Consumer(List<Integer> list) {
this.list = list;
}
@Override
public void run() {
synchronized (list) {
for (int i = 0; i < 10; i++) {
while (list.isEmpty()) {
System.out.println("Consumer is waiting");
try {
list.wait();
} catch (InterruptedException ex) {
ex.printStackTrace();;
}
}
int k = list.remove(0);
System.out.println("consume=" + k);
list.notifyAll();
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
}
public static void main(String[] args) {
Thread producer = new Thread(new Producer(list));
Thread consumer = new Thread(new Consumer(list));
producer.start();
consumer.start();
}
}
Output:
输出:
produce=0
producer is waiting
consume=0
Consumer is waiting
produce=1
producer is waiting
consume=1
Consumer is waiting
produce=2
producer is waiting
consume=2
Consumer is waiting
produce=3
producer is waiting
consume=3
Consumer is waiting
produce=4
producer is waiting
consume=4
Consumer is waiting
produce=5
producer is waiting
consume=5
Consumer is waiting
produce=6
producer is waiting
consume=6
Consumer is waiting
produce=7
producer is waiting
consume=7
Consumer is waiting
produce=8
producer is waiting
consume=8
Consumer is waiting
produce=9
consume=9
回答by Kingshuk Saha
class Resources {
类资源{
private final int capacity = 2;
public static int value = 0;
LinkedList < Integer > list;
Resources() {
list = new LinkedList < > ();
}
void consume() throws InterruptedException {
while (true) {
synchronized(this) {
while (list.size() == 0) {
wait();
}
int val = list.removeFirst();
System.out.println("Value consumed:" + val);
notify();
//Thread.sleep(1000);
}
}
}
void produce() throws InterruptedException {
while (true) {
synchronized(this) {
while (list.size() == capacity) {
wait();
}
System.out.println("Value produced:" + value);
list.add(value++);
notify();
Thread.sleep(1000);
}
}
}
}
}
class MyThread5 extends Thread {
类 MyThread5 扩展线程 {
Resources rs;
String name;
public String getNames() {
return name;
}
public MyThread5(Resources rs, String name) {
this.rs = rs;
this.name = name;
}
@Override
public void run() {
if (this.getNames().equals("Producer")) {
try {
this.rs.produce();
} catch (InterruptedException ex) {
Logger.getLogger(MyThread5.class.getName()).log(Level.SEVERE, null, ex);
}
} else {
try {
this.rs.consume();
} catch (InterruptedException ex) {
Logger.getLogger(MyThread5.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
public class ProducerConsumerExample {
公共类 ProducerConsumerExample {
public static void main(String[] args) {
try {
Resources rs = new Resources();
MyThread5 m1 = new MyThread5(rs, "Producer");
MyThread5 m2 = new MyThread5(rs, "Consumer");
m1.start();
m2.start();
m1.join();
m2.join();
} catch (InterruptedException ex) {
Logger.getLogger(ProducerConsumerExample.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
回答by Anil Nivargi
Don't use list.size() == 10
, instead you can check list.size == 1
.
不要使用list.size() == 10
,您可以检查list.size == 1
。
For producer produced, one wait for the other one till consumer consumes. Refer this Producer Consumer Problem - Solution using wait and notify In Java
对于生产者生产,一个等待另一个直到消费者消费。请参阅此生产者消费者问题 - 在 Java 中使用等待和通知的解决方案