【问题标题】:Working with ExecutorService with smaller thread pool than tasks使用线程池小于任务的 ExecutorService
【发布时间】:2021-06-09 08:53:01
【问题描述】:

我对 ExecutorService 有疑问。 我有Status 的列表,每个状态都包含具有此状态的人员列表。我想做的是

  1. 检索状态列表
  2. 我想同时处理所有处于 S 状态的人。
  3. 状态 S 的处理完成后,我想以相同的方式处理状态 S1,直到处理完所有状态
  4. 返回所有已处理的人

我有这个代码

ExecutorService threadExecutor = Executors.newFixedThreadPool(10);
List<Status> statusList = getStatusList();
List<PersonInfoWrapper> personInfoWrapperList = new ArrayList<>();

for(Status status: statusList ){
    List<PersonInfo> personInfo = status.getPersonList();
    List<Future<PersonInfoWrapper> futures = new ArrayList<>();

    for(PersonInfo info : personInfo){
         Future<PersonInfoWrapper> future = threadExecutor.submit(() -> processInfo(info));
         futures.add(future);
    }

    for(Future<PersonInfoWrapper> future : futures ){
         personInfoWrapperList .add(future.get());
    }
}
threadExecutor.shutdown();

我的问题是:

  1. ExecutorService 有 10 个线程池。但是每个状态的人数都超过 10 个。当我同时处理它时(如第二个for循环所示),然后在第三个for循环中调用future.get(),它不会阻塞ExecutorService中其他任务的执行吗?

  2. 这样重用ExecutorService可以吗?我不应该为即将处理的每个状态都使用新的执行器服务吗?

【问题讨论】:

  • 不,你不应该为每个状态使用新的执行者。
  • @SvetlinZarev 谢谢回答,第一个问题怎么样?

标签: java multithreading threadpool


【解决方案1】:
  1. 我建议你使用 Executors.newCachedThreadPool(),所以如果你有更多的人,那么线程这个投票将根据需要自动创建新线程,并在它们可用时重用以前构造的线程。如果没有可用的现有线程,将创建一个新线程并将其添加到池中。六十秒内未使用的线程将被终止并从缓存中删除。因此,闲置时间足够长的池不会消耗任何资源。

Future 为您提供 isDone() 方法,它不会阻塞,如果计算完成则返回 true,否则返回 false。

Future.get() 用于检索计算结果。

你有几个选择:

  • 调用 isDone(),如果结果准备就绪,通过调用 get() 请求它,注意没有阻塞
  • 用 get() 无限期阻塞
  • 用get(long timeout, TimeUnit unit)阻塞指定超时
  1. 创建多个 executorService 实例是个坏主意。因此,是的,您应该重复使用现有的。

希望,这会有所帮助。

【讨论】:

  • 但是 .get() 是否只阻塞主线程?例如,当我在期货上使用 get() 时,它基本上加入了线程,对吗?所以所有的任务都完成了,然后我等待他们的结果。还是我错了?
  • 它只阻塞主线程。而且future.get()不会影响其他已经执行的线程。
  • 正如你所说,你会等待他们的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-24
  • 2014-08-01
  • 2019-02-10
  • 2017-02-16
  • 1970-01-01
  • 2012-10-29
  • 2015-03-11
相关资源
最近更新 更多