天天看点

基于java的生产者和消费者三种实现方式

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);
    }
           
基于java的生产者和消费者三种实现方式
基于java的生产者和消费者三种实现方式
基于java的生产者和消费者三种实现方式

Github源码:https://github.com/782891085/ProducerAndConsumerDemo