多线程顺序打印 ABC

2020/02/05 Java

synchronized

使用一个同步对象控制,用一个变量控制当前要的输出,一个 while 循环判断输出,不是 wait,是就打印并 notify。

package printabc;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class SynchronizedSolution {
    volatile String printString = "A";

    public static void main(String[] args) {
        SynchronizedSolution lockConditionSolution = new SynchronizedSolution();
        ExecutorService es = Executors.newFixedThreadPool(3);
        SynchronizedSolution.PrintA printA = lockConditionSolution.new PrintA(lockConditionSolution);
        SynchronizedSolution.PrintB printB = lockConditionSolution.new PrintB(lockConditionSolution);
        SynchronizedSolution.PrintC printC = lockConditionSolution.new PrintC(lockConditionSolution);
        es.execute(printA);
        es.execute(printB);
        es.execute(printC);
    }

    class PrintA implements Runnable {
        SynchronizedSolution synchronizedSolution;

        public PrintA(SynchronizedSolution synchronizedSolution) {
            this.synchronizedSolution = synchronizedSolution;
        }

        @Override
        public void run() {
            while (true){
                synchronized (synchronizedSolution){
                    try {
                        while (!printString.equals("A")) {
                            synchronizedSolution.wait(); //由于同步对象是 synchronizedSolution,一定要用他的 wait 和 notify
                        }
                        System.out.println("A");
                        printString = "B";
                        synchronizedSolution.notifyAll(); // 一定要唤醒全部,否则不一定唤醒那个就完全停止了
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    class PrintB implements Runnable {
        SynchronizedSolution synchronizedSolution;

        public PrintB(SynchronizedSolution synchronizedSolution) {
            this.synchronizedSolution = synchronizedSolution;
        }


        @Override
        public void run() {
            while (true){
                synchronized (synchronizedSolution){
                    try {
                        while (!printString.equals("B")) {
                            synchronizedSolution.wait();
                        }
                        System.out.println("B");
                        printString = "C";
                        synchronizedSolution.notifyAll();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    class PrintC implements Runnable {
        SynchronizedSolution synchronizedSolution;

        public PrintC(SynchronizedSolution synchronizedSolution) {
            this.synchronizedSolution = synchronizedSolution;
        }

        @Override
        public void run() {
            while (true){
                synchronized (synchronizedSolution){
                    try {
                        while (!printString.equals("C")) {
                            synchronizedSolution.wait();
                        }
                        System.out.println("C");
                        printString = "A";
                        synchronizedSolution.notifyAll();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

lock + Conidtion

用 lock 锁住,使用三个 Condition 控制对应的接下来唤醒的线程。

package printabc;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class LockConditionSolution {
    Lock lock = new ReentrantLock();
    Condition conditionA = lock.newCondition(); // lock 没有普通的 wait 和 notify 方法!!!!调用也是调用的 object 必须在同步块里的
    Condition conditionB= lock.newCondition();
    Condition conditionC = lock.newCondition();
    volatile String printString = "A";

    public static void main(String[] args) {
        LockConditionSolution lockConditionSolution = new LockConditionSolution();
        ExecutorService es = Executors.newFixedThreadPool(3);
        LockConditionSolution.PrintA printA = lockConditionSolution.new PrintA();
        LockConditionSolution.PrintB printB = lockConditionSolution.new PrintB();
        LockConditionSolution.PrintC printC = lockConditionSolution.new PrintC();
        es.execute(printA);
        es.execute(printB);
        es.execute(printC);
    }

    class PrintA implements Runnable {

        @Override
        public void run() {
            while (true){
                lock.lock();
                try {
                    if (!printString.equals("A")) {
                        conditionA.await();
                    }
                    System.out.println("A");
                    printString = "B";
                    conditionB.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }
    }

    class PrintB implements Runnable {

        @Override
        public void run() {
            while (true){
                lock.lock();
                try {
                    if (!printString.equals("B")) {
                        conditionB.await();
                    }
                    System.out.println("B");
                    printString = "C";
                    conditionC.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();

                }
            }
        }
    }

    class PrintC implements Runnable {

        @Override
        public void run() {
            while (true){
                lock.lock();

                try {
                    if (!printString.equals("C")) {
                        conditionC.await();
                    }
                    System.out.println("C");
                    printString = "A";
                    conditionA.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }
    }
}

Search

    Table of Contents