1. 程式人生 > 實用技巧 >JUC 併發程式設計--07 阻塞佇列版本的 生產者消費者(不使用synchronized和 lock),也有一些疑惑,

JUC 併發程式設計--07 阻塞佇列版本的 生產者消費者(不使用synchronized和 lock),也有一些疑惑,

直接上程式碼: 前提是你已經 熟悉了原子類,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();
    }
}

執行結果:

如果把生產者的 睡一秒, 註釋掉, 會是另一種結果, 這個結果讓我有些疑惑, 你能幫我解惑麼?