执行者服务和scheduleWithFixedDelay()

时间:2013-11-26 21:08:30

标签: java multithreading executorservice

这是我的任务。我在类中有一个静态的作业队列,以及一个向队列添加作业的静态方法。拥有从队列轮询并执行拉取作业的n个线程。我需要让n个线程以一定间隔同时轮询。 AKA,所有3人应该每5秒轮询一次并寻找工作。

我有这个:

public class Handler {

    private static final Queue<Job> queue = new LinkedList<>();

    public static void initialize(int maxThreads) { // maxThreads == 3

        ScheduledExecutorService executorService =
            Executors.newScheduledThreadPool(maxThreads);

        executorService.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                Job job = null;
                synchronized(queue) {
                    if(queue.size() > 0) {
                        job = queue.poll();
                    }
                }
                if(job != null) {
                    Log.log("start job");
                    doJob(job);
                    Log.log("end job");
                }
            }    
        }, 15, 5, TimeUnit.SECONDS);

    }

}

当我添加4个任务时,我得到了这个输出:

startjob
endjob
startjob
endjob
startjob
endjob
startjob
endjob

很明显,这些线程连续执行这些工作,而我需要一次完成3个工作。我究竟做错了什么?谢谢!

3 个答案:

答案 0 :(得分:2)

来自文档:

  

如果执行此任务的时间超过其周期,则后续执行可能会延迟,但不会同时执行。

因此,您必须安排三个独立的任务才能让它们同时运行。另请注意,计划的执行程序服务是一个固定的线程池,对于许多用例而言,它不够灵活。一个好习惯就是使用预定服务将任务提交给常规执行器服务,该服务可以配置为可调整大小的线程池。

答案 1 :(得分:0)

您正在以固定延迟运行ScheduledExecutorService,这意味着您的作业将一个接一个地运行。使用固定线程池,一次提交3个线程。这是an explanation with examples

答案 2 :(得分:0)

如果您声明Job extends Runnable,那么您的代码就会大大简化:

首先将Executor声明为全局可访问的地方:

public static final ExecutorService executor = Executors.newFixedThreadPool(MAX_THREADS);

然后添加这样的工作:

executor.submit(new Job());

你已经完成了。

相关问题