1. 程式人生 > 其它 >生產者和消費者問題

生產者和消費者問題

技術標籤:# JUC

在這裡插入圖片描述

  • synchronized演示生產者和消費者問題

    // 執行緒也可以喚醒,而不會接通知,終端或者超時,即所謂的虛假喚醒,等待應該總是出現在迴圈中,while取代if
    public class TraditionalProConsumer {
        public static void main(String[] args) {
            // 建立資源物件
            Num num = new Num();
            // 開啟執行緒
            new Thread(() -> {
                for (int i = 0; i <
    10; i++) { try { num.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "A").start(); new Thread(() -> { for (int i = 0; i < 10; i++)
    { try { num.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "B").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try {
    num.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "C").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { num.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "D").start(); } } // 資源類 class Num { private int num = 0; //1 public synchronized void increment() throws InterruptedException { while (this.num != 0) { // 等待 this.wait(); } // 業務邏輯 num ++; System.out.println(Thread.currentThread().getName() + "->" + num); // 喚醒 this.notifyAll(); } //1 public synchronized void decrement() throws InterruptedException { while (this.num == 0) { // 等待 this.wait(); } // 業務邏輯 num --; System.out.println(Thread.currentThread().getName() + "->" + num); // 喚醒 this.notifyAll(); } }
  • 通過Lock 找到 Condition演示生產者和消費者問題

    public class LockProConsumer {
        public static void main(String[] args) {
            // 建立資源物件
            Data num = new Data();
            // 開啟執行緒
            new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    num.decrement();
                }
            }, "A").start();
            new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    num.increment();
                }
            }, "B").start();
            new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    num.increment();
                }
            }, "C").start();
            new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    num.decrement();
                }
            }, "D").start();
        }
    }
    
    // 資源類
    class Data {
        private int num = 0;
        // Lock方式
        // 1. 建立一個鎖
        Lock lock = new ReentrantLock();
        // 2. 繫結condition
        Condition condition = lock.newCondition();
    
    
        // +1
        public void increment() {
            // 1. 加鎖
            lock.lock();
            // 2. 業務邏輯
            try {
                while (num != 0) {
                    // 1>. 等待
                    condition.await();
                }
                // 2>. 業務邏輯
                num++;
                System.out.println(Thread.currentThread().getName() + "->" + num);
                // 3>. 喚醒
                condition.signalAll();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 3. 解鎖
                lock.unlock();
            }
        }
    
        // -1
        public void decrement() {
            // 1. 加鎖
            lock.lock();
            // 2. 業務邏輯
            try {
                while (num == 0) {
                    // 1>. 等待
                    condition.await();
                }
                // 2>. 業務邏輯
                num--;
                System.out.println(Thread.currentThread().getName() + "->" + num);
                // 3>. 喚醒
                condition.signalAll();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 3. 解鎖
                lock.unlock();
            }
        }
    }
    
  • 通過Lock 找到 Condition精準通知和喚醒 執行緒

public class LockSeqABCD {
    public static void main(String[] args) {
        Data1 data1 = new Data1();
        // 開啟執行緒
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data1.printA();
            }
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data1.printB();
            }
        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data1.printC();
            }
        }, "C").start();
    }
}

// 資源類
class Data1 {
    // 鎖
    private Lock lock = new ReentrantLock();
    // 三個監視器
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();
    // 資料
    private int num = 1;

    // 三個方法
    public void printA() {
        // 1. 加鎖
        lock.lock();
        // 2. 業務邏輯
        try {
            while (num != 1) {
                // 1>. 判斷等待
                condition1.await();
            }
            // 2>. 業務邏輯
            num = 2;
            System.out.println(Thread.currentThread().getName() + "->AAA");
            // 3>. 喚醒,指定喚醒,用指定的監視器
            condition2.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 3. 解鎖
            lock.unlock();
        }
    }
    public void printB() {
        // 1. 加鎖
        lock.lock();
        // 2. 業務邏輯
        try {
            while (num != 2) {
                // 1>. 判斷等待
                condition2.await();
            }
            // 2>. 業務邏輯
            num = 3;
            System.out.println(Thread.currentThread().getName() + "->AAA");
            // 3>. 喚醒,指定喚醒,用指定的監視器
            condition3.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 3. 解鎖
            lock.unlock();
        }
    }
    public void printC() {
        // 1. 加鎖
        lock.lock();
        // 2. 業務邏輯
        try {
            while (num != 3) {
                // 1>. 判斷等待
                condition3.await();
            }
            // 2>. 業務邏輯
            num = 1;
            System.out.println(Thread.currentThread().getName() + "->AAA");
            // 3>. 喚醒,指定喚醒,用指定的監視器
            condition1.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 3. 解鎖
            lock.unlock();
        }
    }
}