1、概述
生产者和消费者问题是一个经典的线程同步问题。生产者(Producer)生产产品(Product),放入仓库(Repertory);消费者(Consumer)消费产品,从仓库里获取。仓库爆满时生产者等待消费者消费,仓库为空时消费者等待生产者生产。
2、实现
2.1、synchronized
生产者Producer:
public class Producer implements Runnable {
private static final String TAG = "Producer";
private Repertory mRepertory;
Producer(Repertory repertory) {
mRepertory = repertory;
}
@Override
public void run() {
Object product = new Object();
mRepertory.produce(product);
}
}
消费者Consumer:
public class Consumer implements Runnable {
private static final String TAG = "Consumer";
private Repertory mRepertory;
Consumer(Repertory repertory) {
mRepertory = repertory;
}
@Override
public void run() {
mRepertory.consume();
}
}
仓库Repertory1:
public class Repertory1 implements Repertory {
private static final String TAG = "Repertory1";
private static final int MAX_SIZE = 100;
private LinkedList<Object> list = new LinkedList<>();
@Override
public synchronized void produce(Object product) {
while (isFull()) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.add(product);
Log.e(TAG, Thread.currentThread().getName() + "生产了: " + product + ",还剩余:" + size());
notifyAll();
}
@Override
public synchronized void consume() {
while (isEmpty()) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Object product = list.remove();
Log.e(TAG, Thread.currentThread().getName() + "消费了: " + product + ",还剩余:" + size());
notifyAll();
}
public boolean isEmpty() {
return list.isEmpty();
}
public boolean isFull() {
return size() == MAX_SIZE;
}
public int size() {
return list.size();
}
}
2.2、Lock/Condition
仓库Repertory2:
public class Repertory2 implements Repertory {
private static final String TAG = "Repertory2";
private static final int MAX_SIZE = 100;
private LinkedList<Object> list = new LinkedList<>();
private final Lock mLock = new ReentrantLock();
private final Condition mEmptyCondition = mLock.newCondition();
private final Condition mFullCondition = mLock.newCondition();
@Override
public void produce(Object product) {
mLock.lock();
try {
while (isFull()) {
try {
mFullCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.add(product);
Log.e(TAG, Thread.currentThread().getName() + "生产了: " + product + ",还剩余:" + size());
mEmptyCondition.signalAll();
} finally {
mLock.unlock();
}
}
@Override
public void consume() {
mLock.lock();
try {
while (isEmpty()) {
try {
mEmptyCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Object product = list.remove();
Log.e(TAG, Thread.currentThread().getName() + "消费了: " + product + ",还剩余:" + size());
mFullCondition.signalAll();
} finally {
mLock.unlock();
}
}
public boolean isEmpty() {
return list.isEmpty();
}
public boolean isFull() {
return size() == MAX_SIZE;
}
public int size() {
return list.size();
}
}
2.3、BlockingDeque
仓库Reprotory3:
public class Repertory3 implements Repertory {
private static final String TAG = "Repertory3";
private static final int MAX_SIZE = 100;
private BlockingDeque<Object> list = new LinkedBlockingDeque<>(MAX_SIZE);
@Override
public void produce(Object product) {
try {
list.put(product);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG, Thread.currentThread().getName() + "生产了: " + product);
}
@Override
public void consume() {
Object product = null;
try {
product = list.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG, Thread.currentThread().getName() + "消费了: " + product);
}
public boolean isEmpty() {
return list.isEmpty();
}
public boolean isFull() {
return size() == MAX_SIZE;
}
public int size() {
return list.size();
}
}
3、测试
private void execute(Repertory repertory) {
Producer producer1 = new Producer(repertory);
Producer producer2 = new Producer(repertory);
Producer producer3 = new Producer(repertory);
Producer producer4 = new Producer(repertory);
Producer producer5 = new Producer(repertory);
Consumer consumer1 = new Consumer(repertory);
Consumer consumer2 = new Consumer(repertory);
Consumer consumer3 = new Consumer(repertory);
Consumer consumer4 = new Consumer(repertory);
Consumer consumer5 = new Consumer(repertory);
ExecutorService service = Executors.newCachedThreadPool();
service.execute(consumer1);
service.execute(consumer2);
service.execute(consumer3);
service.execute(consumer4);
service.execute(consumer5);
service.execute(producer1);
service.execute(producer2);
service.execute(producer3);
service.execute(producer4);
service.execute(producer5);
}
Github源码:https://github.com/782891085/ProducerAndConsumerDemo