首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java ExecutorService使用

Java ExecutorService使用
EN

Stack Overflow用户
提问于 2018-09-07 11:19:45
回答 2查看 465关注 0票数 1

我想做一个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();

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

EN

回答 2

Stack Overflow用户

发布于 2018-09-07 11:48:43

问得好!我不认为你对awaitTermination()方法有一个清晰的理解。让我们来看看这个文档

块,直到所有任务在关闭请求后完成执行,或超时发生,或当前线程被中断,以先发生者为准。

不应使用awaitTermination()来等待所有任务的完成。如果这是您要寻找的语义,则使用invokeAll()来阻止直到所有任务完成为止。不使用awaitTermination() 而不使用(以前的shutdown() )是不正确的,由于awaitTermination没有关闭执行器,可能会导致您等待一段时间。

在这种情况下,您只是试图强迫应用程序等待线程完成,但如果没有在分配的时间范围内,则需要继续。这个具体的案例让我有点怀疑多线程的使用,因为它看起来有点过于设计,但是为了教育的目的,让我们解释一下如何做到这一点。

基本解

代码语言:javascript
复制
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中一个非常强大的对象,具有很多功能。让我们看看如何改进这个场景。

代码语言:javascript
复制
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秒。

代码语言:javascript
复制
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();
}
票数 3
EN

Stack Overflow用户

发布于 2018-09-07 13:42:22

如何使用预定的执行者服务?您希望运行任务a,希望运行任务b,并希望在20秒后关闭executor服务。

代码语言:javascript
复制
ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
Future<?> futureA = service.submit(()->foo());
ScheduledFuture<?> futureB = service.schedule(()->bar(), 2, TimeUnit.SECONDS);

我不知道你为什么要关闭执行器,但是你可以利用未来等待任务的完成。

代码语言:javascript
复制
Object b = futureB.get(20, TimeUnit.SECONDS);
service.shutdown();
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52221501

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档