Skip to content

Commit fd4d889

Browse files
consumer producer example
1 parent 49d36b9 commit fd4d889

File tree

1 file changed

+127
-0
lines changed

1 file changed

+127
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/**
2+
*
3+
*/
4+
package sporadic.producer_consumer_example;
5+
6+
import java.util.LinkedList;
7+
import java.util.Queue;
8+
import java.util.Random;
9+
10+
/**
11+
* 在 Java 中可以用 wait、notify 和 notifyAll 来实现线程间的通信。
12+
* 举个例子,如果你的Java程序中有两个线程——即生产者和消费者,那么生产者可以通知消费者,让消费者开始消耗数据,
13+
* 因为队列缓冲区中有内容待消费(不为空)。相应的,消费者可以通知生产者可以开始生成更多的数据,
14+
* 因为当它消耗掉某些数据后缓冲区不再为满。
15+
*
16+
* 如何使用Wait
17+
* 尽管关于wait和notify的概念很基础,它们也都是Object类的函数,但用它们来写代码却并不简单。
18+
* 如果你在面试中让应聘者来手写代码,用wait和notify解决生产者消费者问题,我几乎可以肯定他们中的大多数都会无所适从或者犯下一些错误,
19+
* 例如在错误的地方使用 synchronized 关键词,没有对正确的对象使用wait,或者没有遵循规范的代码方法。
20+
* 说实话,这个问题对于不常使用它们的程序员来说确实令人感觉比较头疼。
21+
*
22+
* 第一个问题就是,我们怎么在代码里使用wait()呢?
23+
* 因为wait()并不是Thread类下的函数,我们并不能使用Thread.call()。
24+
* 事实上很多Java程序员都喜欢这么写,因为它们习惯了使用Thread.sleep(),所以他们会试图使用wait() 来达成相同的目的,但很快他们就会发现这并不能顺利解决问题。
25+
*
26+
* 正确的方法是对在多线程间共享的那个Object来使用wait。
27+
*
28+
* 在生产者消费者问题中,这个共享的Object就是那个缓冲区队列。
29+
*
30+
* 第二个问题是,既然我们应该在synchronized的函数或是对象里调用wait,那哪个对象应该被synchronized呢?
31+
* 答案是,那个你希望上锁的对象就应该被synchronized,即那个在多个线程间被共享的对象。在生产者消费者问题中,应该被synchronized的就是那个缓冲区队列。*/
32+
33+
/**
34+
* Simple Java program to demonstrate How to use wait, notify and notifyAll()
35+
* method in Java by solving producer consumer problem.
36+
*
37+
* @author Javin Paul
38+
*/
39+
public class ProducerConsumerInJava {
40+
public static void main(String args[]) {
41+
System.out.println("How to use wait and notify method in Java");
42+
System.out.println("Solving Producer Consumper Problem");
43+
Queue<Integer> sharedQueueOrBuffer = new LinkedList<>();
44+
int maxSize = 10;
45+
Thread producer = new Producer(sharedQueueOrBuffer, maxSize, "PRODUCER");
46+
Thread consumer = new Consumer(sharedQueueOrBuffer, maxSize, "CONSUMER");
47+
producer.start();
48+
consumer.start();
49+
}
50+
}
51+
52+
/**
53+
* Producer Thread will keep producing values for Consumer to consumer. It will
54+
* use wait() method when Queue is full and use notify() method to send
55+
* notification to Consumer Thread.
56+
*
57+
*/
58+
class Producer extends Thread {
59+
private Queue<Integer> queue;
60+
private int maxSize;
61+
62+
public Producer(Queue<Integer> queue, int maxSize, String name) {
63+
super(name);
64+
this.queue = queue;
65+
this.maxSize = maxSize;
66+
}
67+
68+
@Override
69+
public void run() {
70+
while (true) {
71+
synchronized (queue) {
72+
while (queue.size() == maxSize) {
73+
try {
74+
System.out.println("Queue is full, "
75+
+ "Producer thread waiting for "
76+
+ "consumer to take something from queue");
77+
queue.wait();
78+
} catch (Exception ex) {
79+
ex.printStackTrace();
80+
}
81+
}
82+
Random random = new Random();
83+
int i = random.nextInt();
84+
System.out.println("Producing value : " + i);
85+
queue.add(i);
86+
queue.notifyAll();
87+
}
88+
}
89+
}
90+
}
91+
92+
/**
93+
* Consumer Thread will consume values form shared queue. It will also use
94+
* wait() method to wait if queue is empty. It will also use notify method to
95+
* send notification to producer thread after consuming values from queue.
96+
*
97+
*/
98+
class Consumer extends Thread {
99+
private Queue<Integer> queue;
100+
private int maxSize;
101+
102+
public Consumer(Queue<Integer> queue, int maxSize, String name) {
103+
super(name);
104+
this.queue = queue;
105+
this.maxSize = maxSize;
106+
}
107+
108+
@Override
109+
public void run() {
110+
while (true) {
111+
synchronized (queue) {
112+
while (queue.isEmpty()) {
113+
System.out.println("Queue is empty,"
114+
+ "Consumer thread is waiting"
115+
+ " for producer thread to put something in queue");
116+
try {
117+
queue.wait();
118+
} catch (Exception ex) {
119+
ex.printStackTrace();
120+
}
121+
}
122+
System.out.println("Consuming value : " + queue.remove());
123+
queue.notifyAll();
124+
}
125+
}
126+
}
127+
}

0 commit comments

Comments
 (0)