一、java并发编程中,生产消费者模式是一个经典的案例,面试或日常并发处理中时常提及。基于生产消费者模式,通过多线程异步消费来提升系统的吞吐量。生产消费者的模式实现的方式很多,首推皮皮虾感觉最简单的三种。
-
基于synchronized机制 ,使用Object 基类最基础的 wait()、notify()实现。
-
基于Condition 机制实现,java 1.5之后Condition 才应运而生,它的产生主要来替代Object的wait()、notify() 来实现线程之间的协作,相对来讲Condition的await()、signal()这种方式实现线程间协作更加安全和高效。
-
直接使用BlockingQueue实现,基于LinkedBlockingQueue、ArrayBlockingQueue 等子类实现。
-
基于并发编程类Semaphore信号量,通过其acquire()与 release()方法实现(具体实现方式本文不再赘述)。
基于synchronized机制实现:
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
public class ProducerConsumerDemo2 {
private final int MAX_SIZE = 5;
/**
* 并发删除,新增不会报 ConcurrentModificationException异常
*/
private CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();
class ProducerThread extends Thread {
@Override
public void run() {
while (true) {
synchronized (list) {
while (list.size() == MAX_SIZE) {
System.out.println("----》当前集合已满");
//唤醒等待的消费者线程
list.notify();
//当前线程等待
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.add(new Random().nextInt(1000));
//唤醒等待的消费者线程
list.notify();
System.out.println("----》生产一条记录,当前集合长度为" + list.size());
}
}
}
}
class ConsumerThread extends Thread {
@Override
public void run() {
while (true) {
synchronized (list) {
while (list.size() == 0) {
System.out.println("----》当前集合为空");
//唤醒等待的生产者线程
list.notify();
try {
// 消费者线程等待
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.remove(list.stream().findFirst().get());
//唤醒等待的生产者线程
list.notify();
System.out.println("----》消费一条任务,当前集合长度为" + list.size());
}
}
}
}
public static void main(String[] args) {
ProducerConsumerDemo2 mainClass = new ProducerConsumerDemo2();
mainClass.new ProducerThread().start();
mainClass.new ConsumerThread().start();
}
}
基于Condition 机制实现:
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ProductConsumerDemo {
/**
* 设置集合最多的容量
*/
private final static int MAX_SIZE = 6;
/**
* 并发删除,新增不会报 ConcurrentModificationException异常
*/
private final static CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();
private final static Lock lock = new ReentrantLock();
private final static Condition condition = lock.newCondition();
static class ProducerDemo extends Thread {
@Override
public void run() {
while (true) {
lock.lock();
try {
while (list.size() == MAX_SIZE) {
System.out.println("----》当前集合已满");
try {
//当前线程等待 LockSupport.park(this);
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.add(new Random().nextInt(1000));
//唤醒 consume 线程 LockSupport.unpark(node.thread);
condition.signal();
System.out.println("----》生产一条记录,当前集合长度为" + list.size());
try {
Thread.sleep(300);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} finally {
lock.unlock();
}
}
}
}
static class ConsumerDemo extends Thread {
@Override
public void run() {
while (true) {
lock.lock();
try {
while (list.size() == 0) {
System.out.println("----》当前集合为空");
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.remove(list.stream().findFirst().get());
// 唤起 produce 线程
condition.signal();
System.out.println("----》消费一条记录,当前集合长度为" + list.size());
try {
Thread.sleep(300);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} finally {
lock.unlock();
}
}
}
}
public static void main(String[] args) {
new ProductConsumerDemo.ProducerDemo().start();
new ProductConsumerDemo.ConsumerDemo().start();
}
}
直接使用BlockingQueue实现:
/**
* @author Administrator
* @version 1.0
* @description: TODO
* @date 2023-07-31 20:00
*/
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ProductConsumerDemo3 {
/**
* 基于队列实现 队列长队为10
*/
private final static BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
class Producer extends Thread {
@Override
public void run() {
while (true) {
try {
queue.put(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("--->>>生产一条任务,当前队列长度为" + queue.size());
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer extends Thread {
@Override
public void run() {
while (true) {
try {
// 从队列头部获取元素,直到队列有值,否则会阻塞
queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("--->>>消费一条任务,当前队列长度为" + queue.size());
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
ProductConsumerDemo3 productConsumerDemo = new ProductConsumerDemo3();
productConsumerDemo.new Producer().start();
productConsumerDemo.new Consumer().start();
}
}