Java ExecutorService 使用

我想制作一个 2 线程应用程序,如下所示:

  1. 创建2个线程池

  2. 在 #1 线程上运行 foo 方法

  3. 等待 2 秒

  4. 在 #2 线程上运行 bar 方法

  5. 2 个线程池最多应等待 20 秒

ExecutorService executor = Executors.newFixedThreadPool(2);

executor.submit(() -> foo());

executor.awaitTermination(2, TimeUnit.SECONDS);

executor.submit(() -> bar());

if (!executor.awaitTermination(20, TimeUnit.SECONDS))

    executor.shutdownNow();

它不起作用,有什么问题?


繁星淼淼
浏览 203回答 2
2回答

拉丁的传说

好问题!我不认为你对awaitTermination()方法有清楚的了解。让我们来看看这个文件。阻塞直到所有任务在关闭请求后完成执行,或发生超时,或当前线程被中断,以先发生者为准。本awaitTermination()不应该被用于等待所有任务完成。如果这是您正在寻找的语义,请使用invokeAll()阻塞直到所有任务完成。利用awaitTermination() 没有事先shutdown()不当,可能会导致您等待一段时间,由于awaitTermination没有关闭执行人。在这种情况下,您只是试图强制应用程序等待您的线程完成,但如果它不在您分配的时间范围内,您希望继续。这个特定的案例让我对多线程的使用产生了一些质疑,因为它看起来有点过度设计,但出于教育目的,让我们解释一下如何做到这一点。基本解决方案ExecutorService executor = Executors.newFixedThreadPool(2);executor.submit(() -> foo());// Thread.sleep(2000); // Wait for 2 secondsTimeUnit.SECONDS.sleep(2); // Also waits for 2 seconds and a bit more readableexecutor.submit(() -> bar());if (!executor.awaitTermination(20, TimeUnit.SECONDS))&nbsp; &nbsp; 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 onexecutor.submit(() -> bar());if (!executor.awaitTermination(20, TimeUnit.SECONDS))&nbsp; &nbsp; executor.shutdownNow();现在,这是更合适的代码,并且会以更好的代码结构为您提供所需的语义。此外,如果第一个未来在 2 秒之前完成,它将提前解锁,这是对基本解决方案的一点改进!正确关机假设您想等待 20 秒executor以完成,以下是您可以做的额外改进。使用以下代码进行关闭,因为它来自ExecutorService作为关闭示例的文档。在这里,我已将您的等待时间更新为 20 秒。pool.shutdown(); // Disable new tasks from being submittedtry {&nbsp; &nbsp; // Wait a while for existing tasks to terminate&nbsp; &nbsp; if (!pool.awaitTermination(20, TimeUnit.SECONDS)) {&nbsp; &nbsp; &nbsp; pool.shutdownNow(); // Cancel currently executing tasks&nbsp; &nbsp; &nbsp; // Wait a while for tasks to respond to being cancelled&nbsp; &nbsp; &nbsp; if (!pool.awaitTermination(20, TimeUnit.SECONDS))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.err.println("Pool did not terminate");&nbsp; &nbsp; }} catch (InterruptedException ie) {&nbsp; &nbsp; // (Re-)Cancel if current thread also interrupted&nbsp; &nbsp; pool.shutdownNow();&nbsp; &nbsp; // Preserve interrupt status&nbsp; &nbsp; Thread.currentThread().interrupt();}

慕勒3428872

使用预定的执行程序服务怎么样?你想运行任务 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();
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java