消费者生产者模式Java代码实现
阿里问我会不会写,憋了一个小时没写出来
写在前面的知识点:
- 用wait和notify实现,或者ReentrantLock实现都可以,下面用wait,notify
- wait,notify需要在synchronized关键字里面,不然会报错,而且锁会在synchronized代码块结束之后释放
- 采用队列存储数据
下面看代码:
import java.util.LinkedList;
import java.util.Queue;
public class ConsumerAndProducer {
public static void main(String[] args) {
Queue<Integer> queue = new LinkedList<>();
Thread producerThread = new Thread(new Runnable() {
@Override
public void run() {
Producer producer = new Producer(5, queue);
for (int i = 0; i < 10; i++) {
producer.put2(i);
}
}
}, "producer1");
Thread producerThread2 = new Thread(new Runnable() {
@Override
public void run() {
Producer producer = new Producer(3, queue);
for (int i = 0; i < 10; i++) {
producer.put2(i);
}
}
}, "producer2");
Thread consumerThread = new Thread(new Runnable() {
@Override
public void run() {
Consumer consumer = new Consumer(5, queue);
for (int i = 0; i < 10; i++) {
consumer.get2();
}
}
}, "consumer1");
Thread consumerThread2 = new Thread(new Runnable() {
@Override
public void run() {
Consumer consumer = new Consumer(4, queue);
for (int i = 0; i < 10; i++) {
consumer.get2();
}
}
}, "consumer2");
producerThread.start();
producerThread2.start();
consumerThread.start();
consumerThread2.start();
}
}
// producer和consumer都有put/put2,get/get2两种版本,这两种都可以
class Producer {
public Queue<Integer> queue;
public int cap;
public Producer(int cap, Queue<Integer> queue) {
this.cap = cap;
this.queue = queue;
}
public void put(int i) {
while (true) {
synchronized (queue) {
while (queue.size() >= cap) {
try {
System.out.println(Thread.currentThread().getName() + " start to wait");
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+" put "+i);
queue.add(i);
queue.notifyAll();
return;
}
}
}
public void put2(int i) {
while (true) {
synchronized (queue) {
if (queue.size() < cap) {
System.out.println(Thread.currentThread().getName()+" put "+i);
queue.add(i);
queue.notifyAll();
return;
} else {
try {
System.out.println(Thread.currentThread().getName() + " start to wait");
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
class Consumer{
public Queue<Integer> queue;
public int cap;
public Consumer(int cap, Queue<Integer> queue) {
this.cap = cap;
this.queue = queue;
}
public int get() {
while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
try {
System.out.println(Thread.currentThread().getName()+"queue is empty, consumer wait");
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int val = queue.poll();
System.out.println(Thread.currentThread().getName()+" get val => "+val);
queue.notifyAll();
return val;
}
}
}
public int get2() {
while(true) {
synchronized (queue) {
if (queue.size() > 0) {
int val = queue.poll();
System.out.println(Thread.currentThread().getName()+" get val => "+val);
queue.notifyAll();
return val;
} else {
try {
System.out.println(Thread.currentThread().getName()+"queue is empty, consumer wait");
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
get2版本的输出
consumer1queue is empty, consumer wait
producer1 put 0
producer1 put 1
producer1 put 2
producer1 put 3
producer1 put 4
producer1 start to wait
consumer2 get val => 0
consumer2 get val => 1
consumer2 get val => 2
consumer2 get val => 3
consumer2 get val => 4
consumer2queue is empty, consumer wait
producer2 put 0
producer2 put 1
producer2 put 2
producer2 start to wait
consumer2 get val => 0
consumer2 get val => 1
consumer2 get val => 2
consumer2queue is empty, consumer wait
producer1 put 5
producer1 put 6
producer1 put 7
producer1 put 8
producer1 put 9
consumer1 get val => 5
consumer1 get val => 6
consumer1 get val => 7
consumer1 get val => 8
consumer1 get val => 9
consumer1queue is empty, consumer wait
consumer2queue is empty, consumer wait
producer2 put 3
producer2 put 4
producer2 put 5
producer2 start to wait
consumer2 get val => 3
consumer2 get val => 4
consumer1 get val => 5
consumer1queue is empty, consumer wait
producer2 put 6
producer2 put 7
producer2 put 8
producer2 start to wait
consumer1 get val => 6
consumer1 get val => 7
consumer1 get val => 8
consumer1queue is empty, consumer wait
producer2 put 9
consumer1 get val => 9