办法一,应用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 的益处是能够灵便管制工作的执行程序和数量,然而须要留神的是,如果计数器的初始值过大,会导致等待时间过长。因而,须要依据具体情况抉择适合的计数器初始值。