我需要定期执行一些数据收集,因为我想创建一个请求来自不同服务器的数据的任务。某些服务器将花费更多时间来处理请求并返回响应,而不是其他服务器。
这就是我想为每个服务器创建任务并执行异步任务的原因。如果我以下列方式使用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);
}
答案 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,因为它不会抛出任何异常。让你的实际任务在一个缓存的执行器内运行,即使以前的任务还没有完成,也允许多个任务同时运行。