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();
}