多个线程想要执行同一同步代码块,则需要先抢占锁资源,要实现顺序输出ABC还要对同步代码块实现顺序访问,本文将采用synchronized、Lock-Condition、Semaphore的方式实现。如果不了解Lock-Conditionk和Semaphore请先浏览学习我后续发布的JUC章节中相关知识点。

synchronized方式

public class ABCsynchronizedDemo {
    public static void main(String[] args) {
        ABC demo3 = new ABC();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    demo3.test1();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "A").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        demo3.test2();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "B").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        demo3.test3();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "C").start();
    }
}

class ABC {

    private volatile int i = 0;

    public synchronized void test1() throws InterruptedException {
        while (true) {
            while (i != 0) {
                wait();
            }
            System.out.println("A");
            i = 1;
            notifyAll();
        }
    }

    public synchronized void test2() throws InterruptedException {
        while (true) {
            while (i != 1) {
                wait();
            }
            System.out.println("B");
            i = 2;
            notifyAll();
        }
    }

    public synchronized void test3() throws InterruptedException {
        while (true) {
            while (i != 2) {
                wait();
            }
            System.out.println("C");
            i = 0;
            notifyAll();
        }
    }
}

Lock-Condition

public class ABCConditionDemo {

    public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        Condition conditionA = lock.newCondition();
        Condition conditionB = lock.newCondition();
        Condition conditionC = lock.newCondition();
        final int[] i = {0};
        int[] count = {0};

        new Thread(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                try {
                    for (int j = 0; j < 20; j++) {
                        while (i[0] != 0) {
                            conditionA.await();
                        }
                        System.out.println("A");
                        i[0] = 1;
                        conditionB.signalAll();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                try {
                    for (int j = 0; j < 20; j++) {
                        while (i[0] != 1) {
                            conditionB.await();
                        }
                        System.out.println("B");
                        i[0] = 2;
                        conditionC.signalAll();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                try {
                    for (int j = 0; j < 20; j++) {
                        while (i[0] != 2) {
                            conditionC.await();
                        }
                        System.out.println("C");
                        System.out.println("-----------------------" + count[0]++);
                        
                        i[0] = 0;
                        conditionA.signalAll();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            }
        }).start();
    }

}

Semaphore

public class ABCSemaphoreDemo {

    public static void main(String[] args) {

        Semaphore semaphoreA = new Semaphore(1);
        Semaphore semaphoreB = new Semaphore(0);
        Semaphore semaphoreC = new Semaphore(0);
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (true) {
                        semaphoreA.acquire();
                        System.out.println("A");
                        semaphoreB.release();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (true) {
                        semaphoreB.acquire();
                        System.out.println("B");
                        semaphoreC.release();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (true) {
                        semaphoreC.acquire();
                        System.out.println("C");
                        semaphoreA.release();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}