目录
3、使用ExecutorService.awaitTermination()
前言
日常开发中肯定会遇到需要同步执行的线程,即主线程需要等待子线程执行完毕才能继续接下来的操作,并且线程需要在特定的时间内执行完成,例如脚本执行这一类,这时我们就可以使用ExecutorService线程池来完成我们的需求,我了解了下大致有三种方式
1、使用Future.get()
Future简单来说就是对具体的Runnable和Callable任务执行结果进行任务取消、任务查询、获取结果的一个东西,由名字也得得出其应该是指向结果的连接,当获得该对象的时候,其时间上任务并未完成,这也就是它可能被称为Future的一个原因把。所以我们需要调用Future.get()方法来强制获取结果,同时设置超时时间,一旦超时,我们便手动取消该任务,代码例子见如下:
@Test
public void test09() {
ExecutorService executorService = Executors.newFixedThreadPool(10);
// 采用Future
Future<Boolean> future = executorService.submit(() -> {
Thread.sleep(3000);
System.out.println("线程执行完成");
return true;
});
try {
if (future.get(4, TimeUnit.SECONDS)) {
System.out.println("任务执行成功");
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
System.out.println("执行超时");
future.cancel(true);
}
}
2、使用CountDownLatch.await()
该同步辅助类旨在在完成一组正在执行操作的线程之前,允许一个或多个线程一直等待,即同步等待,该方法在完成上述需求时需要事先知道有多少线程数,因为其本身就是类似于一个计数器,最开始需要初始化指定数量的线程,每完成一个,计数器减1,只要计数器的值大于0,则主线程一直阻塞,注意在调用该类的await阻塞等待时最好设置超时时间,否则容易造成死锁,下面看下简单代码实现:
@Test
public void test09() {
ExecutorService executorService = Executors.newFixedThreadPool(100);
CountDownLatch countDownLatch = new CountDownLatch(1);
executorService.execute(() -> {
try {
Thread.sleep(3000);
System.out.println("线程执行完成");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
}
});
try {
if (countDownLatch.await(4, TimeUnit.SECONDS)) {
System.out.println("任务执行成功");
} else {
System.out.println("执行超时");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
3、使用ExecutorService.awaitTermination()
该方法会一直等待所有的任务都结束或超时时间到则立即结束,若所有任务都执行成功则返回true,否则返回false,需要注意的是在最后需关闭当前线程池或手动取消仍在执行的任务,由于需要关闭线程池,所以除非是一次性任务处理事件,否则若是需要重复使用当前线程池,则每次执行时都会重复创建和执行线程池,不是你的最佳选择,看下简单实现:
@Test
public void test09() {
ExecutorService executorService = Executors.newFixedThreadPool(100);
executorService.execute(() -> {
try {
Thread.sleep(3000);
System.out.println("线程执行完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
try {
if (executorService.awaitTermination(2, TimeUnit.SECONDS)) {
System.out.println("主线程开始执行");
} else {
System.out.println("执行超时");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
executorService.shutdown();
}
}