版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weisong530624687/article/details/79293297
24. 写出生产者消费者模式。
生产者消费者模式介绍:
生产者生产数据到缓冲区中,消费者从缓冲区中取数据。
如果缓冲区为空,不能继续消费,则消费者线程阻塞等待,直到缓冲区有新产生可供消费。
常见场景:
比如厂家生产一批东西到商场,顾客消费者到商场买东西,厂家即为生产者,商场即为缓冲区,顾客即为消费者。
缓冲区作用:
1. 解耦,生产者和消费者不直接建立关系,都只依赖缓冲区,而不互相依赖2. 独立运作,支持并发和异步,提升效率
常见的生产者消费者几种实现方式:
方式一:synchronized同步锁,同步队列,配合wait、notifyAll
package com.ws.synchroniz;
import java.util.LinkedList;
import java.util.Queue;
/**
*
* @author WeiS
*
*/
public class MessageQueue {
private static final int size = 10;
private Queue<Integer> messageQueue = new LinkedList<>();
public void put(Integer num) {
synchronized (messageQueue) {
while (messageQueue.size() > size) {
System.err.println(Thread.currentThread().getId() + "等待....[" + num + "]");
try {
messageQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
messageQueue.add(num);
System.err.println(Thread.currentThread().getId() + "放入[" + num + "]");
messageQueue.notifyAll();
}
}
public Integer get() {
Integer take = 0;
synchronized (messageQueue) {
while (messageQueue.isEmpty()) {
System.err.println(Thread.currentThread().getId() + "等待....");
try {
messageQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
take = messageQueue.poll();
System.err.println(Thread.currentThread().getId() + "移除[" + take + "]");
messageQueue.notifyAll();
}
return take;
}
}
方式二:重入锁ReentrantLock、配合Condition、await、signalAll
package com.ws.lock;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
*
* @author WeiS
*
*/
public class MessageQueue {
private static final int size = 10;
private Queue<Integer> messageQueue = new LinkedList<>();
private final Lock reentrantLock = new ReentrantLock();
private final Condition putCondition = reentrantLock.newCondition();
private final Condition getCondition = reentrantLock.newCondition();
public void put(Integer num) {
reentrantLock.lock();
while (messageQueue.size() > size) {
System.err.println(Thread.currentThread().getId() + "..生产等待....[" + num + "]");
try {
putCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
messageQueue.add(num);
System.err.println(Thread.currentThread().getId() + "放入[" + num + "]");
getCondition.signalAll();
reentrantLock.unlock();
}
public Integer get() {
reentrantLock.lock();
Integer take = 0;
while (messageQueue.isEmpty()) {
System.err.println(Thread.currentThread().getId() + "..消费等待....");
try {
getCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
take = messageQueue.poll();
System.err.println(Thread.currentThread().getId() + "移除[" + take + "]");
putCondition.signalAll();
reentrantLock.unlock();
return take;
}
}
方式三:阻塞队列BlockingQueue
package com.ws;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
*
* @author WeiS
*
*/
public class MessageQueue {
private static final int size = 10;
private BlockingQueue<Integer> messageQueue = new LinkedBlockingQueue<>(size);
public void put(Integer num) {
try {
messageQueue.put(num);
System.err.println(Thread.currentThread().getId() + "放入[" + num + "]");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Integer get() {
Integer take = 0;
try {
take = messageQueue.take();
System.err.println(Thread.currentThread().getId() + "移除[" + take + "]");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return take;
}
}
其他生产者、消费者代码参考如下:(可通用)
package com.ws.lock;
import java.util.Random;
/**
*
* @author WeiS
*
*/
public class Producer extends Thread{
private MessageQueue messageQueue;
public Producer(MessageQueue messageQueue) {
super();
this.messageQueue = messageQueue;
}
@Override
public void run() {
while(true) {
try {
Thread.sleep((long) (1000 * Math.random()));
int nextInt = new Random().nextInt(10000);
//System.out.println(Thread.currentThread().getId() + "生产[" + nextInt + "]");
messageQueue.put(nextInt);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
package com.ws.lock;
/**
*
* @author WeiS
*
*/
public class Consumer extends Thread{
private MessageQueue messageQueue;
public Consumer(MessageQueue messageQueue) {
super();
this.messageQueue = messageQueue;
}
@Override
public void run() {
while(true) {
try {
Thread.sleep((long) (1000 * Math.random()));
@SuppressWarnings("unused")
Integer integer = messageQueue.get();
//System.out.println(Thread.currentThread().getId() + "消费[" + integer + "]");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
package com.ws.lock;
public class Main {
public static void main(String[] args) {
MessageQueue messageQueue = new MessageQueue();
Producer producer = new Producer(messageQueue);
Consumer consumer = new Consumer(messageQueue);
Consumer consumer1 = new Consumer(messageQueue);
Consumer consumer2 = new Consumer(messageQueue);
producer.start();
consumer.start();
consumer1.start();
consumer2.start();
}
}
下图可以看下这个阻塞队列的继承过程:
(可点击图片放大查看)
打赏
如果觉得我的文章对你有帮助,有钱就捧个钱场,没钱就捧个人场,欢迎点赞或转发 ,并请注明原出处,谢谢....