Java多线程:ABC循环输出

最近看到个Java多线程的面试题,要求3个线程,分别负责打印A/B/C,要求三个线程按照ABC的顺序输出N次

然后下面是我的解题思路:

首先,多线程问题,无脑起一个ThreadPoolExecutor

ThreadPoolExecutor executor = new ThreadPoolExecutor(poolSize,maxPoolSize,1,TimeUnit.MINUTES, new LinkedBlockingQueue<>(),new MyThreadFactory());

然后由于是要输出N次,在多线程问题中,我们需要一个支持CAS的AtomicInteger来计数

AtomicInteger count = new AtomicInteger(1);
final int target = 10;

然后接下来就是关键了,ABC要顺序输出,也就是要实现以下流程:

  1. 一开始,不允许输出B/C
  2. 输出A后,可以输出B
  3. 输出B后,可以输出C
  4. 输出C后,计数、判断,并且可以输出A

然后细化到A/B/C三个不同的线程中,他们就分别需要做到以下功能:

  1. 一开始,线程B/C阻塞
  2. 线程A需要线程C释放后才能输出A,并且输出后释放线程B,然后阻塞
  3. 线程B需要线程A释放后才能输出B,并且输出后释放线程C,然后阻塞
  4. 线程C需要线程A释放后才能输出C,并且输出后释放线程A,然后阻塞
  5. 以此循环….然后在线程C进行计数、停止的判断

说到资源,我选择了Semaphore这个类,用资源量为1的信号量来请求、释放资源,所以就要有了3个Semaphore

Semaphore A_B = new Semaphore(1);
Semaphore B_C = new Semaphore(1);
Semaphore C_A = new Semaphore(1);

然后就是开始运行三个线程前,对线程B/C的阻塞

A_B.acquire();
B_C.acquire();

最后就是输出部分了

executor.execute(() -> {
    try {
        while (true){
            C_A.acquire();
            System.out.print(count + ":");
            System.out.print("A");
            A_B.release();
        }
    } catch (InterruptedException ignored) {}
});

executor.execute(() -> {
    try {
        while (true){
            A_B.acquire();
            System.out.print("B");
            B_C.release();
        }
    } catch (InterruptedException ignored) {
    }
});

executor.execute(() -> {
    try {
        while (true){
            B_C.acquire();
            System.out.println("C");
            if(count.getAndIncrement() >= target){
                executor.shutdownNow();
            }
            C_A.release();
        }
    } catch (InterruptedException ignored) {
    }
});

最终输出:

1:ABC
2:ABC
3:ABC
4:ABC
5:ABC
6:ABC
7:ABC
8:ABC
9:ABC
10:ABC

完整代码:https://github.com/zhuyst/ThreadPoolExecutor_Learn/blob/master/src/indi/zhuyst/learn/abc/Main.java

你可能感兴趣的:(Java多线程:ABC循环输出)