Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/371.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何实现ExecutorService以轮流执行任务?_Java_Multithreading_Threadpool - Fatal编程技术网

Java 如何实现ExecutorService以轮流执行任务?

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

我使用with来执行任务列表。我的任务列表通常在80-150个左右,我已经将任何时候运行的线程数限制为10个,如下所示:

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