如何让线程C 等待 线程A和线程B执行完后再执行?

214 阅读1分钟

这是一道非常常见的多线程方面的面试题,以下是我想到的几个解决方案:

先封装一个测试方法,输出一个语句

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------- ");  
}