JUC練習代碼-JUC版本實現生產者消費者問題

public class JUCTest02 {
    public static void main(String[] args) throws InterruptedException {
        Data2 data = new Data2();
        new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "C").start();
        new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "D").start();

    }
}

//判斷是否等待,業務,幹完活通知
class Data2 {
    private int number = 0;
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();

    public void increment() throws InterruptedException {
        lock.lock();
        try {

            while (number > 0) {
                //等待
                System.out.println(Thread.currentThread().getName() + "wait");
                condition.await();
            }
            number++;

            //通知其他線程,我+1完畢了
            System.out.println(Thread.currentThread().getName() + "執行了+1" + ";number=" + number);
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();

        } finally {
            lock.unlock();
        }


    }

    public void decrement() throws InterruptedException {
        lock.lock();
        try {

            while (number <= 0) {
                //等待
                System.out.println(Thread.currentThread().getName() + "wait");
                condition.await();
            }
            number--;
            //通知其他線程,我+1完畢了
            System.out.println(Thread.currentThread().getName() + "執行了-1" + ";number=" + number);
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }


    }
}

編寫代碼時注意順序,首先是lock.lock(),然後try 裏面包括業務邏輯,最後finally lock.unlock()
Condition也是JUC包下接口,可以通過lock.newCondition()進行實例化。
Condition中await,signal ,signalAll方法,對應Object的wait,notify,notifyAll方法。

上述代碼樣例打印的部分結果如下所示

A執行了+1;number=1
Await
B執行了-1;number=0
Bwait
A執行了+1;number=1
Await
B執行了-1;number=0
Bwait
C執行了+1;number=1
Cwait
Await
B執行了-1;number=0
Bwait

雖然滿足0,1輸出,但是怎麼保證ABCD也是按照順序打印呢?

其實只要創建多個condition對象,就可以精確等待和喚醒了。如下圖代碼所示:

public class JUCTest02 {
    public static void main(String[] args) throws InterruptedException {
        Data2 data = new Data2();
        new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                try {
                    data.increment1();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                try {
                    data.decrement2();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                try {
                    data.increment3();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "C").start();
        new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                try {
                    data.decrement4();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "D").start();

    }
}

//判斷是否等待,業務,幹完活通知
class Data2 {
    private int number = 0;
    Lock lock = new ReentrantLock();
    Condition condition1 = lock.newCondition();
    Condition condition2 = lock.newCondition();
    Condition condition3 = lock.newCondition();
    Condition condition4 = lock.newCondition();

    public void increment1() throws InterruptedException {
        lock.lock();
        try {

            while (number > 0) {
                //等待
                System.out.println(Thread.currentThread().getName() + "wait");
                condition1.await();
            }
            number++;

            //通知其他線程,我+1完畢了
            System.out.println(Thread.currentThread().getName() + "執行了+1" + ";number=" + number);
            condition2.signal();
        } catch (Exception e) {
            e.printStackTrace();

        } finally {
            lock.unlock();
        }


    }

    public void decrement2() throws InterruptedException {
        lock.lock();
        try {

            while (number <= 0) {
                //等待
                System.out.println(Thread.currentThread().getName() + "wait");
                condition2.await();
            }
            number--;
            //通知其他線程,我+1完畢了
            System.out.println(Thread.currentThread().getName() + "執行了-1" + ";number=" + number);
            condition3.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }


    }

    public void increment3() throws InterruptedException {
        lock.lock();
        try {

            while (number > 0) {
                //等待
                System.out.println(Thread.currentThread().getName() + "wait");
                condition3.await();
            }
            number++;

            //通知其他線程,我+1完畢了
            System.out.println(Thread.currentThread().getName() + "執行了+1" + ";number=" + number);
            condition4.signal();
        } catch (Exception e) {
            e.printStackTrace();

        } finally {
            lock.unlock();
        }


    }

    public void decrement4() throws InterruptedException {
        lock.lock();
        try {

            while (number <= 0) {
                //等待
                System.out.println(Thread.currentThread().getName() + "wait");
                condition4.await();
            }
            number--;
            //通知其他線程,我+1完畢了
            System.out.println(Thread.currentThread().getName() + "執行了-1" + ";number=" + number);
            condition1.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }


    }

部分打印結果,如下所示:

A執行了+1;number=1
Await
B執行了-1;number=0
Bwait
C執行了+1;number=1
Cwait
D執行了-1;number=0
Dwait
A執行了+1;number=1
Await
B執行了-1;number=0
Bwait
C執行了+1;number=1
Cwait
D執行了-1;number=0
Dwait
A執行了+1;number=1
Await
B執行了-1;number=0
Bwait
C執行了+1;number=1
Cwait
D執行了-1;number=0
Dwait
A執行了+1;number=1
Await
B執行了-1;number=0
Bwait
C執行了+1;number=1
Cwait
D執行了-1;number=0
Dwait
A執行了+1;number=1
Await
B執行了-1;number=0
Bwait
C執行了+1;number=1
Cwait
D執行了-1;number=0
Dwait
A執行了+1;number=1
Await
B執行了-1;number=0
Bwait
C執行了+1;number=1
Cwait
D執行了-1;number=0
Dwait
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章