設計模式-生產者消費者模式 常見場景: 某個模組負責產生資料,這些資料由另一個模組來負責處理。產生資料的模組,就形象地稱為生產者;而處理資料的模組,就稱為消費者。 該模式還需要有一個緩衝區處於生
阿新 • • 發佈:2019-01-02
常見場景:
某個模組負責產生資料,這些資料由另一個模組來負責處理。產生資料的模組,就形象地稱為生產者;而處理資料的模組,就稱為消費者。
該模式還需要有一個緩衝區處於生產者和消費者之間,作為一箇中介。生產者把資料放入緩衝區,而消費者從緩衝區取出資料
緩衝區作用
1. 解耦,生產者和消費者只依賴緩衝區,而不互相依賴
2. 支援併發和非同步
方式一,同步佇列
/** * 生產者、消費者緩衝區 */ public class Storage implements IStorage { private final int maxSize = 10; private Queue<Object> queue = newLinkedList<Object>(); @Override public void put(Object obj) { synchronized (queue) { while (queue.size() > maxSize) { System.out.println("緩衝區已滿,不能進入"); try { queue.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } queue.add(obj); System.out.println("進入緩衝區"); queue.notifyAll(); } } @Override public Object get() { Object obj = null; synchronized (queue) { while (queue.size() <= 0) { System.out.println("緩衝區為空, 進入等待"); try { queue.wait(); }catch (InterruptedException e) { e.printStackTrace(); } } obj = queue.poll(); System.out.println("離開緩衝區"); queue.notifyAll(); } return obj; } }
方式二,可重入鎖
public class Storage implements IStorage { private final int maxSize = 20; private LinkedList<Object> list = new LinkedList<Object>(); private final Lock lock = new ReentrantLock(); // 倉庫滿的條件變數 private final Condition full = lock.newCondition(); // 倉庫空的條件變數 private final Condition empty = lock.newCondition(); @Override public void put(Object obj) { lock.lock(); while (list.size() >= maxSize) { try { System.out.println("緩衝區已滿,不能進入"); // 生產阻塞 full.await(); } catch (InterruptedException e) { e.printStackTrace(); } } list.add(obj); System.out.println("進入緩衝區"); empty.signalAll(); lock.unlock(); } @Override public Object get() { lock.lock(); while (list.size() <= 0) { try { System.out.println("緩衝區為空, 進入等待"); // 消費阻塞 empty.await(); } catch (InterruptedException e) { e.printStackTrace(); } } Object obj = list.remove(); System.out.println("離開緩衝區"); full.signalAll(); lock.unlock(); return obj; } }
方式三,阻塞佇列
public class Storage implements IStorage { private LinkedBlockingQueue<Object> list = new LinkedBlockingQueue<Object>(10); @Override public void put(Object obj) { try { list.put(obj); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("進入緩衝區"); } @Override public Object get() { Object obj = null; try { obj = list.take(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("離開緩衝區"); return obj; } }