Java 使用Phaser等待线程池任务完成

Java 使用Phaser等待线程池任务完成,java,multithreading,threadpoolexecutor,phaser,Java,Multithreading,Threadpoolexecutor,Phaser,只有在提交到线程池的所有任务完成后,我才想从我的executeTasks()方法返回。请注意,我的线程池具有可配置的threadpoolsize,并使用SynchronousQueue作为后备队列,因此我的for循环只在线程可用时才通过提交任务安全地进行。所以,我只想等待最后的任务。我使用的是相位器 我已经创建了一个包含1个注册方(即当前线程)的移相器,在向线程池提交任务之前,我向该移相器注册了一个新的参与方,当任务完成时,我取消了该任务参与方的注册。当for循环通过提交最终任务完成时,我希望我

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

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

我想这会解决我的问题。请让我知道,如果我错了,或者如果有任何其他更好的方法来做到这一点。Countdownlatch不会有帮助,因为我的threadpoolsize是可配置的。我知道有一个计数器和监视器可以解决这个问题,但我想要像移相器一样的开箱即用的解决方案

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();
}
private void executeTasks(ADPool执行器线程池,迭代器it){
最终相量相器=新相量器(1);
for(最终字符串id:IteratorUtils.iterable(it)){
相量寄存器();
threadPool.execute(()->{
//相位器到达();
试一试{
线程长度(10000*id.length());
}最后{
相位器。到达并注销();
}
});
}
相位器。到达并等待前进();
相位器。到达并注销();
}

我以前从未使用过
相位器
,但我认为
倒计时锁存器
是处理此任务的更好方法

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

使用
倒计时闩锁时,有两种方法很有用:

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

private void executeTasks(ADPool执行器线程池,迭代器it){
final CountDownLatch CountDownLatch=新的CountDownLatch(threadPool.getPoolSize());
for(最终字符串id:IteratorUtils.iterable(it)){
threadPool.execute(()->{
试一试{
线程长度(10000*id.length());
countdownlock.countDown();
}catch(InterruptedException ex){}
});
}
倒计时闩锁。等待();
}

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

invokeAll()
不是您的选项吗?不,我不想让等待调用的任务排队。我实现了这一点,这一点很有效。如果有人发现任何漏洞或更好的方法,请告诉我。哦,对不起。我应该提到,我的线程池大小是可配置的,countdownlatch对我没有帮助,这无关紧要,因为您将线程池作为参数传递。它只需要获得池大小中的线程数如果我想增加池大小怎么办?我无法向右递增倒计时闩锁
倒计时闩锁
不需要知道如何增加池大小。如果您在方法
executeTasks
中看到,我将线程池中的线程数作为闩锁的参数传递。是的,我理解这一点,但我的意思是,在执行任务期间,我希望增加线程池的大小。但由于countdownlatch是使用初始线程池大小创建的,因此无法对其进行调整。此外,您的实现假设每个线程只有一个任务,但事实并非如此。
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();
  }