2 回答
TA贡献1789条经验 获得超8个赞
好问题!我不认为你对awaitTermination()方法有清楚的了解。让我们来看看这个文件。
阻塞直到所有任务在关闭请求后完成执行,或发生超时,或当前线程被中断,以先发生者为准。
本awaitTermination()不应该被用于等待所有任务完成。如果这是您正在寻找的语义,请使用invokeAll()阻塞直到所有任务完成。利用awaitTermination() 没有事先shutdown()不当,可能会导致您等待一段时间,由于awaitTermination没有关闭执行人。
在这种情况下,您只是试图强制应用程序等待您的线程完成,但如果它不在您分配的时间范围内,您希望继续。这个特定的案例让我对多线程的使用产生了一些质疑,因为它看起来有点过度设计,但出于教育目的,让我们解释一下如何做到这一点。
基本解决方案
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(() -> foo());
// Thread.sleep(2000); // Wait for 2 seconds
TimeUnit.SECONDS.sleep(2); // Also waits for 2 seconds and a bit more readable
executor.submit(() -> bar());
if (!executor.awaitTermination(20, TimeUnit.SECONDS))
executor.shutdownNow();
虽然这不是理想的代码,但它会给你你正在寻找的语义。
改进
该executor.submit()会返回一个Future<T>对象。这是 Java 中一个非常强大的对象,并且具有很多功能。让我们看看如何改进场景。
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<T> foo = executor.submit(() -> foo());
T result = foo.get(2, TimeUnit.SECONDS); // Attempt to grab the result for 2 seconds, then move on
executor.submit(() -> bar());
if (!executor.awaitTermination(20, TimeUnit.SECONDS))
executor.shutdownNow();
现在,这是更合适的代码,并且会以更好的代码结构为您提供所需的语义。此外,如果第一个未来在 2 秒之前完成,它将提前解锁,这是对基本解决方案的一点改进!
正确关机
假设您想等待 20 秒executor以完成,以下是您可以做的额外改进。使用以下代码进行关闭,因为它来自ExecutorService作为关闭示例的文档。在这里,我已将您的等待时间更新为 20 秒。
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(20, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(20, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
TA贡献1848条经验 获得超6个赞
使用预定的执行程序服务怎么样?你想运行任务 a,你想运行任务 b,你想在 20 秒后关闭执行程序服务。
ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
Future<?> futureA = service.submit(()->foo());
ScheduledFuture<?> futureB = service.schedule(()->bar(), 2, TimeUnit.SECONDS);
不知道为什么要关闭执行器,但是可以使用future来等待任务的完成。
Object b = futureB.get(20, TimeUnit.SECONDS);
service.shutdown();
添加回答
举报