JUC 併發程式設計--07 阻塞佇列版本的 生產者消費者(不使用synchronized和 lock),也有一些疑惑,
阿新 • • 發佈:2020-08-28
直接上程式碼: 前提是你已經 熟悉了原子類,volatile,和阻塞佇列
public class JucPCdemo03 { /** * 阻塞佇列的應用: 這裡實現的生產者消費者,生產一個消費一個 * 且,不使用 synchronized 和 lock鎖 */ private volatile boolean flag = true; private static AtomicInteger atomicInteger = new AtomicInteger(0); private BlockingQueue<String> blockingQueue; public JucPCdemo03(BlockingQueue<String> blockingQueue) { this.blockingQueue = blockingQueue; System.out.println(blockingQueue.getClass().getName()); } //生產方法 public void producer() throws InterruptedException { String data = null; boolean result; while(flag){ data = atomicInteger.incrementAndGet()+""; result = blockingQueue.offer(data, 2, TimeUnit.SECONDS); if(result){ System.out.println(Thread.currentThread().getName() + "--生產者--新增佇列成功--data:" + data); }else{ System.out.println(Thread.currentThread().getName() + "--生產者--超出等待時間, 退出等待"); } //我在這裡有疑惑? : 你能幫我解決麼? // 這裡睡1秒,不能少,因為 atomicInteger加1的操作是原子的,加入阻塞佇列的操作是併發的,會導致同一時間內,有多個元素加入到了阻塞佇列中,返回都是true,即使規定阻塞佇列容量為1, // 所以這裡的疑惑是: 阻塞佇列容量為1, 併發情況下,卻多個數據都加入佇列成功了?為什麼 TimeUnit.SECONDS.sleep(1); } System.out.println(); System.out.println(); System.out.println(); System.out.println("生產者停止生產了"); } //消費方法 public void consumer() throws InterruptedException { String data = null; while(flag){ data = blockingQueue.poll(2, TimeUnit.SECONDS); if(null == data || "".equals(data)){ System.out.println(Thread.currentThread().getName() + "--消費者--超出等待時間.退出等待,消費停止"); flag = false; return; }else{ System.out.println(Thread.currentThread().getName() + "--消費者--消費成功,消費的資料為: data:" + data); } } System.out.println(); System.out.println(); System.out.println(); System.out.println("消費者停止消費了"); } public void stop(){ flag = false; } public static void main(String[] args) throws InterruptedException { JucPCdemo03 jucPCdemo03 = new JucPCdemo03(new ArrayBlockingQueue<>(1)); new Thread(()->{ try { jucPCdemo03.producer(); } catch (InterruptedException e) { e.printStackTrace(); } },"生產者執行緒啟動").start(); new Thread(()->{ try { jucPCdemo03.consumer(); } catch (InterruptedException e) { e.printStackTrace(); } },"消費者執行緒啟動").start(); TimeUnit.SECONDS.sleep(5); jucPCdemo03.stop(); } }
執行結果:
如果把生產者的 睡一秒, 註釋掉, 會是另一種結果, 這個結果讓我有些疑惑, 你能幫我解惑麼?