多线程打印01 02 03 04 05 ...

发布时间 2023-08-30 16:36:15作者: JaxYoun

多线程打印01 02 03 04 05 ...

原文:https://www.cnblogs.com/hapjin/p/17501458.html
多线程打印:01 02 03 04 05 ...

  1. main 函数中的while(true)表示线程会一直争抢锁,进行打印
  2. 通过检查条件变量是否满足,来决定打印0、还是打印奇数、还是打印偶数
  3. volatile 变量enableOdd 在打印0之后,进行切换:决定打印奇数 or 打印偶数
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.IntConsumer;

/**
 * @date 2022/6/5
 * 打印 01 02 03 04 05 06 ...
 */
public class ZeroEvenOdd {

    private static IntConsumer intConsumer = x -> System.out.println(x);

    private ReentrantLock lock = new ReentrantLock();
  
    private Condition zeroCondition = lock.newCondition();
    private Condition oddCondition = lock.newCondition();
    private Condition evenCondition = lock.newCondition();

    private volatile boolean printZero = true;
    private volatile boolean printOdd = false;
    private volatile boolean printEven = false;

    //控制下一次是打印奇数,还是打印偶数
    private volatile boolean enableOdd = false;

    public static void main(String[] args) {
        ZeroEvenOdd zeroEvenOdd = new ZeroEvenOdd();

        Thread t1 = new Thread(() -> {
            while (true) {
                try {
                    zeroEvenOdd.zero();
                    sleep(1);
                } catch (Exception e) {

                }
            }
        });

        Thread t2 = new Thread(() -> {
            int i = 1;
            //while 循环
            while (true) {
                try {
                    zeroEvenOdd.even(i += 2);
                    sleep(1);
                } catch (InterruptedException e) {
                    System.out.println(e);
                }
            }
        });

        Thread t3 = new Thread(() -> {
           int i = 2;
            while (true) {
                try {
                    zeroEvenOdd.odd(i += 2);
                    sleep(1);
                } catch (InterruptedException e) {
                    System.out.println(e);
                }
            }
        });

        t1.start();
        t2.start();
        t3.start();
    }

    // printNumber.accept(x) outputs "x", where x is an integer.
    public void zero() throws InterruptedException {
        try {
            lock.lock();
            while (!printZero) {
                zeroCondition.await();
            }
            //若不赋值为false,main方法while true循环可能再次由此线程抢到锁,会导致重复连续打印2个0
            printZero = false;
            intConsumer.accept(0);


            if (enableOdd) {
                //打印偶数
                printOdd = true;
                //下一次打印奇数
                enableOdd = false;
                //通知偶数打印
                oddCondition.signal();
            }else {
                printEven = true;
                enableOdd = true;
                evenCondition.signal();
            }
        } finally {
            lock.unlock();
        }
    }

    public void even(int i) throws InterruptedException {
        try {
            lock.lock();
            while (!printEven) {
                evenCondition.await();
            }
            //已经打印了奇数,下一个打印不能是奇数,这里必须显示赋值为false,避免此线程下一次又抢到了锁,造成重复打印2个奇数
            printEven = false;
            intConsumer.accept(i);
            //
            printZero = true;
            zeroCondition.signal();
        } finally {
            lock.unlock();
        }
    }

    public void odd(int i) throws InterruptedException {
        try {
            lock.lock();
            while (!printOdd) {
                oddCondition.await();
            }
            printOdd = false;
            intConsumer.accept(i);
            printZero = true;
            zeroCondition.signal();
        } finally {
            lock.unlock();
        }
    }


    private static void sleep(long sec) {
        try {
            TimeUnit.SECONDS.sleep(sec);
        } catch (InterruptedException e) {
            System.out.println(e);
        }
    }
}