生产者消费者设计模式含义
生产者消费者模式解耦了消息生产和消费过程,生产者生产消息数据,消费者对其消费。生产者无需知道生产的消息被谁消费,消费者也无需知道谁生产了数据。
很明显,生产者消费者设计模式采用了异步的消息通信,它们之间存在一种消息的通知机制,如java中的wait/nofity操作。
下面我们实现该模式
原理及完整实现代码
原理:角色有生产者线程和消费者线程,
生产者往消息队列里put消息(如果队列满则等待阻塞),并且通知消费者可以进行消费了。
消费者不断的从队列里take消息(队列为空则等待阻塞),并且通知生产者可以生产了。
Message消息类
public class Message {
private String data;
public Message(String data) {
this.data = data;
}
public String getData() {
return data;
}
@Override
public String toString() {
return "Message{" +
"data='" + data + '\'' +
'}';
}
}
MessageQueue消息队列类
public class MessageQueue {
private final LinkedList<Message> queue;
private final int limit;
public MessageQueue(int limit) {
this.limit = limit;
this.queue = new LinkedList<Message>();
}
public void put(Message message) throws InterruptedException {
synchronized (queue) {
if (queue.size() > limit) {
queue.wait();
}
queue.addLast(message);
queue.notifyAll();
}
}
public Message take() throws InterruptedException {
synchronized (queue) {
while (queue.isEmpty()) {
queue.wait();
}
Message message = queue.removeLast();
queue.notifyAll();
return message;
}
}
}
ProducerThread生产者线程类
public class ProducerThread extends Thread {
private final MessageQueue queue;
private static AtomicInteger atomicInteger = new AtomicInteger(0);
private static Random random = new Random();
public ProducerThread(int seq, MessageQueue queue) {
super("PRODUCER-" + seq);
this.queue = queue;
}
@Override
public void run() {
while (true) {
try {
Message message = new Message("Message-" + atomicInteger.incrementAndGet());
queue.put(message);
System.out.println(String.format("%s put message %s", Thread.currentThread().getName(), message));
TimeUnit.MILLISECONDS.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
break;
}
}
}
}
ConsumerThread消费者线程类
public class ConsumerThread extends Thread {
private final MessageQueue queue;
private static AtomicInteger atomicInteger = new AtomicInteger(0);
private static Random random = new Random();
public ConsumerThread(int seq, MessageQueue queue) {
super("COMSUMER-" + seq);
this.queue = queue;
}
@Override
public void run() {
while (true) {
try {
Message message = queue.take();
System.out.println(String.format("%s take message %s", Thread.currentThread().getName(), message));
TimeUnit.MILLISECONDS.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
break;
}
}
}
}
Client类
public class Client {
public static void main(String[] args) {
MessageQueue messageQueue = new MessageQueue(1000);
new ProducerThread(1,messageQueue).start();
new ProducerThread(2,messageQueue).start();
new ConsumerThread(1,messageQueue).start();
new ConsumerThread(2,messageQueue).start();
}
}