Skip to content

并发编程实战之三个线程同时运行交替打印 A B C

Synchronized 和 wait, notifyAll 的实现方式

java
package com.mengweijin.learning.basic.lock;

/**
 * 三个线程同时运行交替打印 A B C,每个线程执行 3 次,总共打印 9 行
 * ThreadA->ThreadB->ThreadC循环执行三个线程
 * 锁释放之后所有线程疯抢争夺资源
 *
 * @author mengweijin
 */
public class AbcSynchronized {
    public static void main(String[] args) {
        Printer printer = new Printer();

        new Thread(() -> printer.print("A", 1, 2), "t1").start();
        new Thread(() -> printer.print("B", 2, 3), "t2").start();
        new Thread(() -> printer.print("C", 3, 1), "t3").start();
    }

     static class Printer {
        int flag = 1;
        public void print(String context, int waitFlag, int nextFlag) {
            try {
                for (int i = 0; i < 3; i++) {
                    synchronized (this) {
                        while(flag != waitFlag) {
                            this.wait();
                        }
                        System.out.println(Thread.currentThread().getName() + ":" + context);
                        flag = nextFlag;
                        this.notifyAll();
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

ReentrantLock 和 Condition 的实现方式

java
package com.mengweijin.learning.basic.lock;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 三个线程同时运行交替打印 A B C,每个线程执行 3 次,总共打印 9 行
 * ThreadA->ThreadB->ThreadC循环执行三个线程
 * 锁释放之后所有线程疯抢争夺资源
 *
 * @author mengweijin
 */
public class AbcReentrantLock {

    public static void main(String[] args) {
        Printer printer = new Printer();

        new Thread(() -> printer.print("A", 1, 2), "t1").start();
        new Thread(() -> printer.print("B", 2, 3), "t2").start();
        new Thread(() -> printer.print("C", 3, 1), "t3").start();
    }

    static class Printer {
        static final ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();

        int flag = 1;
        public void print(String context, int waitFlag, int nextFlag) {
            for (int i = 0; i < 5; i++) {
                lock.lock();
                try {
                    while (flag != waitFlag) {
                        condition.await();
                    }
                    System.out.println(Thread.currentThread().getName() + ":" + context);
                    flag = nextFlag;
                    condition.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }
    }
}

ReentrantLock 和 Condition 的实现方式 —— 优化一

java
package com.mengweijin.learning.basic.lock;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 三个线程同时运行交替打印 A B C,每个线程执行 3 次,总共打印 9 行
 * ThreadA->ThreadB->ThreadC循环执行三个线程
 * 锁释放之后所有线程按照条件唤醒,不用再疯抢争夺资源
 *
 * @author mengweijin
 */
public class AbcReentrantLockBest {

    private static final int TIMES = 3;

    public static void main(String[] args) {
        Printer printer = new Printer();

        new Thread(() -> {
            for (int i = 0; i < TIMES; i++) {
                printer.printA("A", 1, 2);
            }
        }, "t1").start();
        new Thread(() -> {
            for (int i = 0; i < TIMES; i++) {
                printer.printB("B", 2, 3);
            }
        }, "t2").start();
        new Thread(() -> {
            for (int i = 0; i < TIMES; i++) {
                printer.printC("C", 3, 1);
            }
        }, "t3").start();
    }

    static class Printer {
        static final ReentrantLock lock = new ReentrantLock();
        Condition conditionA = lock.newCondition();
        Condition conditionB = lock.newCondition();
        Condition conditionC = lock.newCondition();

        int flag = 1;

        public void printA(String context, int waitFlag, int nextFlag) {
            lock.lock();
            try {
                while (flag != waitFlag) {
                    conditionA.await();
                }
                System.out.println(Thread.currentThread().getName() + ":" + context);
                flag = nextFlag;
                conditionB.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }

        public void printB(String context, int waitFlag, int nextFlag) {
            lock.lock();
            try {
                while (flag != waitFlag) {
                    conditionB.await();
                }
                System.out.println(Thread.currentThread().getName() + ":" + context);
                flag = nextFlag;
                conditionC.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }

        public void printC(String context, int waitFlag, int nextFlag) {
            lock.lock();
            try {
                while (flag != waitFlag) {
                    conditionC.await();
                }
                System.out.println(Thread.currentThread().getName() + ":" + context);
                flag = nextFlag;
                conditionA.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
}

ReentrantLock 和 Condition 的实现方式 —— 优化二

java
package com.mengweijin.learning.basic.lock;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 三个线程同时运行交替打印 A B C,每个线程执行 3 次,总共打印 9 行
 * ThreadA->ThreadB->ThreadC循环执行三个线程
 * 锁释放之后所有线程按照条件唤醒,不用再疯抢争夺资源
 *
 * @author mengweijin
 */
public class AbcReentrantLockBestOptimize {

    private static final int TIMES = 3;

    public static void main(String[] args) {
        Printer printer = new Printer();

        new Thread(() -> printer.print("A", 1, 2, printer.conditionA, printer.conditionB), "t1").start();
        new Thread(() -> printer.print("B", 2, 3, printer.conditionB, printer.conditionC), "t2").start();
        new Thread(() -> printer.print("C", 3, 1, printer.conditionC, printer.conditionA), "t3").start();
    }

    static class Printer {
        static final ReentrantLock lock = new ReentrantLock();
        Condition conditionA = lock.newCondition();
        Condition conditionB = lock.newCondition();
        Condition conditionC = lock.newCondition();

        int flag = 1;

        public void print(String context, int waitFlag, int nextFlag, Condition waitCondition, Condition signalCondition) {
            for (int i = 0; i < TIMES; i++) {
                lock.lock();
                try {
                    while (flag != waitFlag) {
                        waitCondition.await();
                    }
                    System.out.println(Thread.currentThread().getName() + ":" + context);
                    flag = nextFlag;
                    signalCondition.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }
    }
}