Java多线程(ABC循环输出)

最近看到个Java多线程的面试题,要求3个线程,分别负责打印A/B/C,要求三个线程按照ABC的顺序输出N次
【Java多线程(ABC循环输出)】然后下面是我的解题思路:
首先,多线程问题,无脑起一个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

    推荐阅读