在多个线程上安排多个任务

时间:2013-12-10 17:04:35

标签: java multithreading scheduler

我需要定期执行一些数据收集,因为我想创建一个请求来自不同服务器的数据的任务。某些服务器将花费更多时间来处理请求并返回响应,而不是其他服务器。

这就是我想为每个服务器创建任务并执行异步任务的原因。如果我以下列方式使用ScheduledExecutorService,每个任务将在自己的线程中执行,还是所有任务都将在同一个线程中执行?

如果任务抛出异常会发生什么,所有其他计划任务都会失败?

this.scheduler = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
                @Override
                public Thread newThread(Runnable r) {
                    return new Thread(r, "collectionThread");
                }
            });

for (String url:urls){
    this.scheduler.scheduleWithFixedDelay(new CollectorTask(url),
                                                  startupDelaySeconds,
                                                  scheduleRateSeconds,
                                                  TimeUnit.SECONDS);
}

2 个答案:

答案 0 :(得分:2)

您正在使用单线程执行程序服务,因此所有任务都按顺序执行。如果其中任何一个抛出异常,则所有后续任务执行都将被取消。

您可以使用

Executors.newScheduledThreadPool(4)  // 4 is the max number of parallel jobs

...允许并行执行并将提交作业的主体包装到

try {
    ...
} catch(Exception e){
    logger.warn("exception during task execution", e);
}

记录错误而不传播它们。

可能存在轻微延迟(几毫秒),并且取决于操作系统,任务将永远不会超过其预定时间执行。由于之前的长时间运行或缺少空闲线程,任务的执行可能会延迟,但以下执行将按原始计划运行:initialDelay + n * period

答案 1 :(得分:0)

是的,你要做的是创建两个线程执行器。第一个是一个预定的执行程序,它接受一个可以启动实际runnable的runnable。所有这些runnable都会创建一个可运行任务的实例,并将其提交给真正的执行者。该执行程序应该只是一个处理任务的普通线程池。

private final ScheduledExecutorService scheduledExecutor = Executors
            .newSingleThreadScheduledExecutor();
private final ExecutorService executor = Executors.newCachedThreadPool();

    private class SubmitTaskRunnable implements Runnable {

        @Override
        public void run() {
            executor.execute(new TaskRunnable());
        }

    }

在您的预定执行程序上安排SubmitTaskRunnable,因为它不会抛出任何异常。让你的实际任务在一个缓存的执行器内运行,即使以前的任务还没有完成,也允许多个任务同时运行。