用ReentrantLock和Condition實現生產者和消費者模式 wait、notify應用場景(生產者-消費者模式)
阿新 • • 發佈:2018-12-19
前面一篇文章《wait、notify應用場景(生產者-消費者模式)》是一種生產者消費者模式實現,今晚這是Lock方式實現,下面是原始碼:
生產者程式碼:
/** * 生產者 * * @author tangquanbin * @date 2018/12/18 22:10 */ public class Producer implements Runnable { /** * 產品容器 */ private List<Integer> container; private Lock lock; /** * 生產者條件 */ private Condition producerCondition; /** * 消費者條件 */ private Condition consumerCondition; public Producer(List<Integer> container, Lock lock, Condition producerCondition, Condition consumerCondition) { this.container = container; this.lock = lock; this.producerCondition = producerCondition; this.consumerCondition = consumerCondition; } public void produce() { //產品容器容量大小 int capacity = 5; try { //獲得鎖 lock.lock(); //容器滿了,不在生產 if (container.size() == capacity) { System.out.println("生產滿了。。。。"); producerCondition.await(); } Random random = new Random(); int p = random.nextInt(50); //模擬1秒生產一個產品 TimeUnit.MILLISECONDS.sleep(1000); System.out.println("生產產品:" + p); container.add(p); //生產一個產品,通知消費者 consumerCondition.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { //釋放鎖 lock.unlock(); } } @Override public void run() { while (true) { produce(); } } }
消費者程式碼:
/** * @author tangquanbin * @date 2018/12/18 22:16 */ public class Consumer implements Runnable{ /** * 產品容器 */ private List<Integer> container; private Lock lock; /** * 生產者條件 */ private Condition producerCondition; /** * 消費者條件 */ private Condition consumerCondition; public Consumer(List<Integer> container, Lock lock, Condition producerCondition, Condition consumerCondition) { this.container = container; this.lock = lock; this.producerCondition = producerCondition; this.consumerCondition = consumerCondition; } /** * 消費者消費產品 */ private void consume(){ try { //獲得鎖 lock.lock(); //容器大小為null,不消費 if (container.size() == 0) { System.out.println("消費完了。。。。"); consumerCondition.await(); } Integer p = container.remove(0); //模擬1秒消費一個產品 TimeUnit.MILLISECONDS.sleep(1000); System.out.println("消費產品:" + p); //消費了,通知生產者 producerCondition.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { //釋放鎖 lock.unlock(); } } @Override public void run() { while (true){ consume(); } } }
測試程式碼:
public class ProducerConsumerTest { public static void main(String[] args) { List<Integer> container = new ArrayList<>(); Lock lock = new ReentrantLock(); Condition producerCondition = lock.newCondition(); Condition consumerCondition = lock.newCondition(); Thread producer = new Thread(new Producer(container,lock,producerCondition,consumerCondition)); Thread consumer = new Thread(new Consumer(container,lock,producerCondition,consumerCondition)); producer.start(); consumer.start(); } }
ReentrantLock 公平鎖和非公平鎖
非公平鎖:獲取鎖的方式是搶佔式的,隨機的。預設ReentrantLock()是非公平的。jdk1.8原始碼如下:
public ReentrantLock() { sync = new NonfairSync(); }
公平鎖:執行緒獲取鎖的順序是按照執行緒加鎖的順序來分配的。ReentrantLock(true)是公平的。jdk1.8原始碼如下:
public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }