我使用java.util.concurrent.ExecutorService和固定线程池来执行任务列表。我的任务列表通常在80-150个左右,我已经将任何时候运行的线程数限制为10个,如下所示:
ExecutorService threadPoolService = Executors.newFixedThreadPool(10);
for ( Runnable task : myTasks )
{
threadPoolService.submit(task);
}
我的用例要求即使完成的任务也应该重新提交给ExecutorService,但是只有当所有已经提交的任务都被服务/完成时,才应该再次执行/获取。也就是说,提交的任务基本上应该轮流执行。因此,在这种情况下不会有threadPoolService.shutdown()
或threadPoolService.shutdownNow()
调用。
我的问题是,如何实现ExecutorService服务轮换基础任务?
我建议以下解决方案完全使用标准库并发utils中存在的功能。它使用一个带有任务装饰器类的CyclicBarrier
和一个重新提交所有任务的障碍动作:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Rotation {
private static final class RotationDecorator implements Runnable {
private final Runnable task;
private final CyclicBarrier barrier;
RotationDecorator( Runnable task, CyclicBarrier barrier ) {
this.task = task;
this.barrier = barrier;
}
@Override
public void run() {
this.task.run();
try {
this.barrier.await();
} catch(InterruptedException e) {
; // Consider better exception handling
} catch(BrokenBarrierException e) {
; // Consider better exception handling
}
}
}
public void startRotation( List<Runnable> tasks ) {
final ExecutorService threadPoolService = Executors.newFixedThreadPool( 10 );
final List<Runnable> rotatingTasks = new ArrayList<Runnable>( tasks.size() );
final CyclicBarrier barrier = new CyclicBarrier( tasks.size(), new Runnable() {
@Override
public void run() {
Rotation.this.enqueueTasks( threadPoolService, rotatingTasks );
}
} );
for(Runnable task : tasks) {
rotatingTasks.add( new RotationDecorator( task, barrier ) );
}
this.enqueueTasks( threadPoolService, rotatingTasks );
}
private void enqueueTasks( ExecutorService service, List<Runnable> tasks ) {
for(Runnable task : tasks) {
service.submit( task );
}
}
}
答案与用于ExecutorService
实例的工作队列的实现更相关。因此,我建议:
>
不要使用Executors.new…
来创建新的ThreadPoolExecutor
使用直接构造函数,例如
公共线程池执行器(int corePoolsize,int最大池大小,long保留AliveTime,TimeUnit单位,BlockingQueue
这样,除非您命令执行程序关闭,否则它将尝试从其工作队列(任务的循环容器)中获取要执行的下一个任务。
ThreadPoolExecutor为afterExecution提供了一个扩展点,您可以将作业放回队列末尾。
public class TaskRepeatingThreadPoolExecutor extends ThreadPoolExecutor {
public TaskRepeatingThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
this.submit(r);
}
}
当然,您需要做更多的工作来自己实例化它,而无需借助ExecutorService
的便捷工厂方法,但是构造函数非常简单,可以进行摸索。
问题内容: 我使用带有固定线程池的java.util.concurrent.ExecutorService执行任务列表。我的任务列表通常约为80-150,并且我将随时运行的线程数限制为10,如下所示: 我的用例要求即使完成的任务也应重新提交给 ExecutorService, 但只有在服务/完成所有 已 提交的任务后才应再次执行/采用。基本上,提交的任务应以轮换为基础执行。因此,在这种情况下不会有
问题内容: 我有三个连接的线程,即第二个线程在第一个死后执行。 这是我的代码: 我将如何使用而不是三个线程对象来实现此功能? 问题答案: 如果您想要/需要的是一个接一个地执行一组作业,但要在与主应用程序线程不同的单个线程中执行,请使用。
问题内容: 我们有一个问题。:) 我们要确保任何时候只有N个线程在执行后台任务。为此,我们使用了固定线程池执行程序。它似乎工作正常。 然后我们发现了一个问题。假设您有一个使用执行程序执行一些并行工作的类,然后在执行程序线程中调用了另一个类,该线程也执行一些并行工作,打算等待它。这是发生了什么: 主线程调用第一级方法。 这种方法认为它可以并行化为16个任务,并拆分其工作。 16个任务被提交给执行者。
问题内容: 快速回顾一下-我有一个Java EE前端,可以接受用户请求,然后针对每个请求使用ExecutorService(SingleThreadedExecutor设置为守护程序)启动冗长的工作流,该工作流包含在库中并且可以工作很好,并且在通过Eclipse以独立模式运行时按预期运行。当从website(servlet)调用时,我观察到工作流始终在初始化Velocity Engine(Velo
要并行或异步运行一些东西,我可以使用ExecutorService:
问题内容: 我正在实现一个线程池机制,在该机制中我想执行具有不同优先级的任务。我希望有一个很好的机制,通过该机制,我可以向服务提交高优先级的任务,并将其安排在其他任务之前。任务的优先级是任务本身的固有属性(无论我对a 还是a 表示任务对我来说都不重要)。 现在,从表面上看,我可以在中使用a 作为任务队列,但是该队列包含对象,这些对象可能是也可能不是我提交给它的任务。而且,如果我已经提交了任务,则不