Java 如何实现ExecutorService以轮流执行任务?
我使用with来执行任务列表。我的任务列表通常在80-150个左右,我已经将任何时候运行的线程数限制为10个,如下所示:Java 如何实现ExecutorService以轮流执行任务?,java,multithreading,threadpool,Java,Multithreading,Threadpool,我使用with来执行任务列表。我的任务列表通常在80-150个左右,我已经将任何时候运行的线程数限制为10个,如下所示: ExecutorService threadPoolService = Executors.newFixedThreadPool(10); for ( Runnable task : myTasks ) { threadPoolService.submit(task); } 我的用例要求,即使是已完成的任务也应该再次提交给ExecutorServic
ExecutorService threadPoolService = Executors.newFixedThreadPool(10);
for ( Runnable task : myTasks )
{
threadPoolService.submit(task);
}
我的用例要求,即使是已完成的任务也应该再次提交给ExecutorService,但只有在所有已提交的任务都得到服务/完成时,才应该再次执行/执行它。也就是说,提交的任务基本上应该轮流执行。因此,在这种情况下将不会有threadPoolService.shutdown()
或threadPoolService.shutdownNow()
调用
我的问题是,如何实现Executor服务轮换基准任务?ThreadPoolExecutor为后执行提供了一个扩展点,您可以将作业放回队列末尾
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);
}
}
公共类TaskRepeatingThreadPoolExecutor扩展ThreadPoolExecutor{
公共任务RepeatingThreadPoolExecutor(int corePoolSize、int maximumPoolSize、long keepAliveTime、时间单位、BlockingQueue workQueue){
super(corePoolSize、maximumPoolSize、keepAliveTime、unit、workQueue);
}
@凌驾
执行后受保护的无效(可运行的r、可丢弃的t){
super.afterExecute(r,t);
提交(r);
}
}
当然,您需要做更多的工作来实例化它,而无需借助
ExecutorService
的便捷工厂方法,但是构造函数非常简单,可以进行摸索。答案更多地与ExecutorService
实例所使用的工作队列的实现有关。因此,我建议:
Executors.new…
来创建新的ThreadPoolExecutor
使用公共线程池执行器(int corePoolSize、int maximumPoolSize、long keepAliveTime、TimeUnit、BlockingQueue workQueue)
这样,除非您命令执行器关闭,否则它将尝试从队列中提取下一个任务,以便从其工作队列(任务的循环容器)执行。我建议以下解决方案,该解决方案完全使用标准库并发UTIL中现有的功能。它使用一个
CyclicBarrier
和一个task decorator类以及一个barrier操作来重新提交所有任务:
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 );
}
}
}
import java.util.ArrayList;
导入java.util.List;
导入java.util.concurrent.BrokenBarrierException;
导入java.util.concurrent.CyclicBarrier;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
公课轮换{
私有静态最终类RotationDecorator实现Runnable{
私有最终可运行任务;
私人自行车终点障碍;
RotationDecorator(可运行任务、CyclicBarrier屏障){
this.task=任务;
这个障碍=障碍;
}
@凌驾
公开募捐{
this.task.run();
试一试{
这个。障碍。等待();
}捕捉(中断异常e){
考虑更好的异常处理
}捕获(断线承运人例外){
考虑更好的异常处理
}
}
}
公共无效启动(列出任务){
final ExecutorService threadPoolService=Executors.newFixedThreadPool(10);
最终列表rotatingTasks=newArrayList(tasks.size());
final CyclicBarrier barrier=new CyclicBarrier(tasks.size(),new Runnable()){
@凌驾
公开募捐{
Rotation.this.enqueueTasks(threadPoolService,rotatingTasks);
}
} );
for(可运行任务:任务){
添加(新的RotationDecorator(任务,障碍));
}
此.enqueueTasks(threadPoolService、rotatingTasks);
}
私有void排队任务(ExecutorService服务、列表任务){
for(可运行任务:任务){
服务提交(任务);
}
}
}
您只需检查所有任务是否已执行,一旦执行完毕,即可重新提交,例如:
List<Future> futures = new ArrayList<>();
for (Runnable task : myTasks) {
futures.add(threadPoolService.submit(task));
}
//wait until completion of all tasks
for (Future f : futures) {
f.get();
}
//restart
......
List futures=new ArrayList();
for(可运行任务:myTasks){
futures.add(threadPoolService.submit(任务));
}
//等待所有任务完成
for(未来f:未来){
f、 get();
}
//重新启动
......
编辑似乎您希望在任务完成后立即重新提交。您可以使用,它使您能够在任务执行时检索任务,-请参见下面的一个简单示例,其中包含两个任务,这些任务在完成后会被重新提交几次。样本输出: 任务1已提交池-1-线程-1
任务2已提交池-1-线程-2
任务1已完成池-1-线程-1
任务1已提交池-1-线程-3
任务2已完成池-1-线程-2
任务1已完成池-1-线程-3
任务2已提交池-1-线程-4
任务1已提交池-1-线程-5
任务1已完成池-1-线程-5
任务2已完成池1线程4
公共类Test1{
公共最终ConcurrentMap ConcurrentMap=新ConcurrentHashMap();
公共最终AtomicInteger重试次数=新的AtomicInteger();
公共最终对象锁=新对象();
公共静态void main(字符串[]args)引发InterruptedException、ExecutionException{
整数计数=0;
List myTasks=new ArrayList();
myTasks.add(getRun
public class Test1 {
public final ConcurrentMap<String, String> concurrentMap = new ConcurrentHashMap<>();
public final AtomicInteger retries = new AtomicInteger();
public final Object lock = new Object();
public static void main(String[] args) throws InterruptedException, ExecutionException {
int count = 0;
List<Runnable> myTasks = new ArrayList<>();
myTasks.add(getRunnable(1));
myTasks.add(getRunnable(2));
ExecutorService threadPoolService = Executors.newFixedThreadPool(10);
CompletionService<Runnable> ecs = new ExecutorCompletionService<Runnable>(threadPoolService);
for (Runnable task : myTasks) {
ecs.submit(task, task);
}
//wait until completion of all tasks
while(count++ < 3) {
Runnable task = ecs.take().get();
ecs.submit(task, task);
}
threadPoolService.shutdown();
}
private static Runnable getRunnable(final int i) {
return new Runnable() {
@Override
public void run() {
System.out.println("Task " + i + " submitted " + Thread.currentThread().getName() + " ");
try {
Thread.sleep(500 * i);
} catch (InterruptedException ex) {
System.out.println("Interrupted");
}
System.out.println("Task " + i + " completed " + Thread.currentThread().getName() + " ");
}
};
}
}