代码之家  ›  专栏  ›  技术社区  ›  Patt

ExecutorService和ForkJoinPool

  •  2
  • Patt  · 技术社区  · 9 年前

    我创建了一个ExecutorService,如下所示-

    ExecutorService executorSer = Executors.newFixedThreadPool(SIZE);
    

    我有一个元素列表(list)和一个操作(称为a),我需要在这个列表中的每个元素上应用。列表可以包含1到1000之间的任意数量的元素。 操作的类型为Callable。 在Operation-A内部,它会呼叫其他2个服务B和C。 B和C也作为异步操作运行,并提交到同一线程池。

    我为每个任务创建了一个异步任务,以并行执行,如下所示:

    CompletionService<T> completionService =  new ExecutorCompletionService<T>(executorSer);
    completionService.submit(A)  // this returns a Future<T>
    

    现在我有一个“未来列表”,我循环该列表以获得()结果。

    如果我在LIST中有一个非常大的线程池和少量的元素,那么一切都很好。 然而,如果线程池SIZE小而LIST大,我就会陷入死锁。 这是因为所有Operation-A请求都很快提交,并占用线程池中的所有线程。每一次行动A都被封锁在未来。它提交的操作B和C的get()。操作B和C任务只是坐在队列中等待线程。

    所以,为了解决这个问题,我改用了ForkJoinPool。我简单地用ForkJoinPool替换了newFixedThreadPool,如下所示

    ExecutorService executorSer = new ForkJoinPool(SIZE); 
    

    并将其余代码保持不变。

    这解决了我的问题。如果线程池SIZE小而LIST大,那么现在就没有死锁了。 我的问题是,为什么? 此外,当我打印螺纹名称时,我看到螺纹号大于尺寸。它只是产生新的线程来解决死锁吗?

    1 回复  |  直到 7 年前
        1
  •  0
  •   iullianr    8 年前

    没有 Executors.ForkJoinPool(SIZE) 方法 java.util.concurrent.Executors 班然而,有 Executors.newWorkStealingPool(int parallelism) 方法创建ForkJoinPool。正如JAVA API所提到的:

    并行级别对应于最大线程数 积极参与或可参与任务处理。 这个 线程的实际数量可以动态增长和收缩。

    这就是你的答案。您提供的参数不是将由执行器管理的实际线程的最大数量(就像 FixedThreadPool 执行人)。