办法一,应用 ExecutorService 和 Future
在 Java 中,能够应用 ExecutorService 和 Future 接口来判断线程池中的工作是否执行结束。上面是一个简略的示例:
ExecutorService executor = Executors.newFixedThreadPool(10); // 创立一个大小为 10 的线程池
List<Future<?>> futures = new ArrayList<>(); // 用于保留提交到线程池中的工作
// 提交工作到线程池中
for (int i = 0; i < 100; i++) {Future<?> future = executor.submit(new Runnable() {
@Override
public void run() {// 执行工作}
});
futures.add(future);
}
// 期待所有工作实现
for (Future<?> future : futures) {
try {future.get(); // 期待工作执行结束
} catch (InterruptedException | ExecutionException e) {// 解决异样}
}
// 敞开线程池
executor.shutdown();
在这个示例中,咱们首先创立了一个大小为 10 的线程池,而后提交了 100 个工作到线程池中,并应用 Future 接口保留这些工作的执行后果。最初,咱们应用一个循环来期待所有工作执行结束,通过调用 Future.get() 办法来期待每个工作的执行后果,如果工作执行过程中产生了异样,咱们能够在 catch 代码块中进行解决。最初,咱们调用 shutdown() 办法来敞开线程池。
须要留神的是,如果线程池中的工作产生了异样,应用 Future.get() 办法会抛出 ExecutionException 异样,须要在代码中进行解决。同时,如果工作执行工夫过长,能够应用 Future.get(long timeout, TimeUnit unit) 办法来指定等待时间。
办法二,应用 shutdown() 办法和 awaitTermination()
除了应用 Future 接口之外,还能够通过调用 ExecutorService 的 shutdown() 办法和 awaitTermination() 办法来判断线程池执行结束。
ExecutorService executor = Executors.newFixedThreadPool(10); // 创立一个大小为 10 的线程池
// 提交工作到线程池中
for (int i = 0; i < 100; i++) {executor.submit(new Runnable() {
@Override
public void run() {// 执行工作}
});
}
executor.shutdown(); // 期待线程池中的工作执行结束
try {executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {// 解决异样}
在这个示例中,咱们首先创立了一个大小为 10 的线程池,而后提交了 100 个工作到线程池中。接下来,咱们调用 shutdown() 办法来敞开线程池,该办法会使线程池回绝新的工作,并期待线程池中的工作执行结束。最初,咱们应用 awaitTermination() 办法来期待所有工作执行结束,该办法会阻塞以后线程,直到线程池中的所有工作执行结束。
须要留神的是,如果线程池中的工作执行工夫过长,须要依据具体的状况调整等待时间,免得阻塞太长时间。
办法三,应用 CountDownLatch 类
另外一种判断线程池执行结束的办法是应用 CountDownLatch 类。CountDownLatch 能够用来阻塞一个或多个线程,直到某个操作实现。
ExecutorService executor = Executors.newFixedThreadPool(10); // 创立一个大小为 10 的线程池
CountDownLatch latch = new CountDownLatch(100); // 创立一个计数器,初始值为 100
// 提交工作到线程池中
for (int i = 0; i < 100; i++) {executor.submit(new Runnable() {
@Override
public void run() {
// 执行工作
latch.countDown(); // 计数器减 1}
});
}
try {latch.await(); // 期待计数器归 0
} catch (InterruptedException e) {// 解决异样}
在这个示例中,咱们创立了一个大小为 10 的线程池,而后提交了 100 个工作到线程池中。接下来,咱们创立了一个初始值为 100 的 CountDownLatch 计数器,每个工作执行结束后会调用 countDown() 办法将计数器减 1。最初,咱们应用 await() 办法来期待计数器归 0,该办法会阻塞以后线程,直到计数器的值为 0。
应用 CountDownLatch 的益处是能够灵便管制工作的执行程序和数量,然而须要留神的是,如果计数器的初始值过大,会导致等待时间过长。因而,须要依据具体情况抉择适合的计数器初始值。