当前位置: 首页 > 知识库问答 >
问题:

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

马权
2023-03-14

我使用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服务轮换基础任务?

共有3个答案

令狐和裕
2023-03-14

我建议以下解决方案完全使用标准库并发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 );
        }
    }

}
公良凯
2023-03-14

答案与用于ExecutorService实例的工作队列的实现更相关。因此,我建议:

>

不要使用Executors.new…来创建新的ThreadPoolExecutor使用直接构造函数,例如

公共线程池执行器(int corePoolsize,int最大池大小,long保留AliveTime,TimeUnit单位,BlockingQueue

这样,除非您命令执行程序关闭,否则它将尝试从其工作队列(任务的循环容器)中获取要执行的下一个任务。

邢雨华
2023-03-14

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 作为任务队列,但是该队列包含对象,这些对象可能是也可能不是我提交给它的任务。而且,如果我已经提交了任务,则不