【问题标题】:Wait for completion of threadpool tasks using Phaser使用 Phaser 等待线程池任务完成
【发布时间】:2017-03-10 15:55:50
【问题描述】:

只有在提交到线程池的所有任务都完成后,我才想从我的executeTasks() 方法返回。请注意,我的线程池具有可配置的线程池大小并使用SynchronousQueue 作为后备队列,因此我的 for 循环仅在线程可用时通过提交任务来安全地进行。所以,我只想等待最后的任务。我为此使用Phaser

我已经创建了一个带有 1 个注册方的 Phaser,即当前线程,并且我在向线程池提交任务之前向 Phaser 注册了一个新方,当任务完成时,我取消注册任务方。当 for 循环通过提交最终任务完成时,我希望我的 arriveAndAwaitAdvance() 将等待注册方到达,但它只会在一段时间后发现所有这些方都被取消注册,然后继续前进并从我的方法返回。

我认为这将解决我的问题。如果我错了,或者是否有其他更好的方法,请告诉我。 Countdownlatch 不会有帮助,因为我的线程池大小是可配置的。我知道有一个计数器和监视器可以解决这个问题,但我想要像 Phaser 这样的开箱即用的解决方案。

private void executeTasks(TheadPoolExecutor threadPool, Iterator<String> it) {
    final Phaser phaser = new Phaser(1);

    for (final String id : IteratorUtils.iterable(it)) {
        phaser.register();
        threadPool.execute(() -> {
        // phaser.arrive();
            try {
                thread.sleep(10000 * id.length());
            } finally {
                phaser.arriveAndDeregister();
            }
        });
    }
    phaser.arriveAndAwaitAdvance();
    phaser.arriveAndDeregister();
}

【问题讨论】:

  • invokeAll() 不适合您吗?
  • 不,我不想排队等待调用的任务
  • 我实现了这个并且这个工作。如果有人发现任何漏洞或更好的方法,请告诉我。 ??????

标签: java multithreading threadpoolexecutor phaser


【解决方案1】:

我以前从未使用过Phaser,但我认为CountDownLatch 是处理此任务的更好方法。

CountDownLatch 是一个同步屏障,它允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。

在使用CountDownLatch 时有两种方法很有用:

  • countDown 在任务完成时递减计数器。
  • await 用于当前线程(例如 main)等待其他线程完成。

*

private void executeTasks(TheadPoolExecutor threadPool, Iterator<String> it) {
    final CountDownLatch countDownLatch = new CountDownLatch(threadPool.getPoolSize());

    for (final String id : IteratorUtils.iterable(it)) {
        threadPool.execute(() -> {
            try {
                thread.sleep(10000 * id.length());
                countDownLatch.countDown();
            } catch (InterruptedException ex) {}
        });
    }
    countDownLatch.await();
  }

这里 CountDownLatch 使用线程池中的线程数进行初始化。

【讨论】:

  • 哦,对不起。我应该提到我的线程池大小是可配置的,countdownlatch 对我没有帮助
  • 没关系,因为你传递了一个threadPool作为参数。只需要获取poolsize中的线程数
  • 如果我想增加池大小怎么办?我无法向右增加倒计时锁存器
  • CountDownLatch 不需要知道增加池大小。如果你在方法executeTasks中看到,我将线程池中的线程数作为参数传递给latch。
  • 是的,我明白这一点,但我是说在执行任务期间我想增加线程池大小。但由于 countdownlatch 是使用初始线程池大小创建的,因此无法调整。此外,您的实现假设每个线程只有一个任务,但事实并非如此。
猜你喜欢
  • 2011-06-02
  • 2015-08-29
  • 2010-10-16
  • 2019-10-24
  • 2020-03-27
  • 1970-01-01
  • 2014-03-18
  • 2015-07-13
相关资源
最近更新 更多