这是一道非常常见的多线程方面的面试题,以下是我想到的几个解决方案:
先封装一个测试方法,输出一个语句
private void runThenSleep(String threadName){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(threadName + " is run ");
}
``
# Join
最简单的就是使用`join` 方法阻塞线程C,等线程A和线程B执行完了再执行线程C
```java
/**
* joinTest
* @throws InterruptedException
*/
@Test
public void joinTest() throws InterruptedException {
Thread threadA = new Thread(()->{
runThenSleep("A");
});
Thread threadB = new Thread(()->{
runThenSleep("B");
});
Thread threadC = new Thread(()->{
try {
threadA.join();
threadB.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
runAndSleep("C");
});
threadC.start();
threadA.start();
threadB.start();
threadC.join();
System.out.println(" ------end------- ");
}
CountDownLatch
然后就是使用 CountDownLatch 来完成拦截执行的动作,这个相对 join 来说 功能更加强大,因为 join 是等待线程执行完毕,而 CountDownLatch 只是等待一个状态位而已,可以由开发自行指定什么时候上报这个状态。
@Test
public void CountDownLatchTest() throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(2);
Thread threadA = new Thread(()->{
runThenSleep("A");
countDownLatch.countDown();
});
Thread threadB = new Thread(()->{
runThenSleep("B");
countDownLatch.countDown();
});
Thread threadC = new Thread(()->{
try {
countDownLatch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
runAndSleep("C");
});
threadA.start();
threadB.start();
threadC.start();
threadC.join();
System.out.println(" ------end------- ");
}
CompletableFuture
最后是一个异步任务编排的大杀器:CompletableFuture ,CompletableFuture可以用于执行异步操作并获取其结果,也可以将多个CompletableFuture组合在一起,实现复杂的异步操作流程。
@Test
public void CompletableFutureTest() throws InterruptedException, ExecutionException {
Thread threadA = new Thread(()->{
runThenSleep("A");
});
Thread threadB = new Thread(()->{
runThenSleep("B");
});
Thread threadC = new Thread(()->{
runThenSleep("C");
});
CompletableFuture<Void> completableFuture = CompletableFuture
.allOf(CompletableFuture.runAsync(threadA), CompletableFuture.runAsync(threadB))
.thenRun(threadC);
completableFuture.get();
System.out.println(" ------end------- ");
}