多线程交替打印问题利用ReentrantLock的通用解决方案

401 阅读1分钟

面试中经常会问到多线程交替打印问题,一般都是2个线程或者3个线程,网上方案也是一大堆。这里利用ReentrantLock底层的公平锁机制实现了n个线程从0交替打印到m。

public class Test {
    // 打印线程之间使用的公平锁
    private  final ReentrantLock lock = new ReentrantLock(true);
    // 启动时保证线程顺序的公平锁
    private  final ReentrantLock lock1 = new ReentrantLock(true);
    // lock对应的condition
    private  Condition condition;
    // lock1对应的condition
    private  Condition condition1;

    /**
     * 交替打印方法实现 threadCount个线程交替打印从0-endNum的数字
     * @param threadCount 线程数量
     * @param endNum 结束打印数字
     * @throws InterruptedException
     */
    public void method(int threadCount, int endNum)  throws InterruptedException {
        condition = lock.newCondition();
        condition1 = lock1.newCondition();

        for (int i = 0;i < threadCount;i++) {
            try {
                lock1.lock();
                new Thread4(i, threadCount, endNum).start();
                condition1.await();
            } finally {
                lock1.unlock();
            }

        }
        try {
            lock.lock();
            condition.signal();
        } finally {
            lock.unlock();
        }
    }

    class Thread4 extends Thread {
        // 当前数字
        private int count;
        // 每个数字之间步长
        private int step;
        // 结束数字
        private int end;


        public Thread4(int count,int step,int end) {
            this.count = count;
            this.step = step;
            this.end = end;
        }

        @Override
        public void run() {
            try {
                lock.lock();
                //用于保证线程执行顺序
                lock1.lock();
                condition1.signal();
                lock1.unlock();
                
                while (count < end) {
                    condition.await();
                    count += step;
                    condition.signal();
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                lock.unlock();
            }

        }
    }
}