概述
ScheduledExecutorService是一种可以在给定延迟后调度命令运行,或周期性执行命令的ExecutorService。schedule 方法创建具有不同延迟的任务,并返回一个可用于取消或检查执行的任务对象。scheduleAtFixedRate 和 scheduleWithFixedDelay 方法创建并执行周期性运行直到取消的任务。使用 Executor.execute(Runnable) 和 ExecutorService submit 方法提交的命令将使用零延迟进行调度。schedule 方法允许使用相对延迟和周期作为参数,而不是绝对时间或日期。将 java.util.Date 表示的绝对时间转换为所需格式是很简单的事情。例如,要在某个将来的日期安排任务,可以使用:schedule(task, date.getTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS)。然而,请注意,由于网络时间同步协议,时钟偏差或其他因素,相对延迟的到期可能不会与任务启用时的当前日期重合。Executors 类提供了本包中提供的 ScheduledExecutorService 实现的方便的工厂方法。
源码解析
提交一个单次任务,在给定延迟后启用。
参数: command – 要执行的任务 delay – 从现在开始延迟执行的时间 unit – 延迟参数的时间单位
返回: 一个 ScheduledFuture,表示任务尚未完成,其 get() 方法在完成后将返回 null。
public ScheduledFuture<?> schedule(Runnable command,long delay, TimeUnit unit);
提交一个带返回值的单次任务,在给定延迟后启用。
参数: callable – 要执行的函数 delay – 从现在开始延迟执行的时间 unit – 延迟参数的时间单位
类型参数: <V> – callable 的结果类型
返回: 一个 ScheduledFuture,可用于提取结果或取消。
public <V> ScheduledFuture<V> schedule(Callable<V> callable,long delay, TimeUnit unit);
提交一个周期性任务,在给定的初始延迟后首先启用,然后按照给定的周期进行; 也就是说,执行将在 initialDelay 后开始,然后是 initialDelay + period,然后是 initialDelay + 2 * period,以此类推。 任务执行序列将无限期地继续下去,直到发生以下异常完成之一: 任务通过返回的 future 明确取消。 执行器终止,这也导致任务取消。 任务的执行抛出异常。在这种情况下,调用返回的 future 的 get 将抛出 ExecutionException,并将该异常作为其原因。 后续执行被禁止。返回的 future 的后续 isDone() 调用将返回 true。 如果此任务的任何执行时间超过其周期,则后续执行可能会延迟,但不会并发执行。
参数: command – 要执行的任务 initialDelay – 首次执行的延迟时间 period – 连续执行之间的周期 unit – initialDelay 和 period 参数的时间单位
返回: 代表重复任务系列未完成的 ScheduledFuture。future 的 get() 方法永远不会正常返回,并在任务取消或任务执行异常终止时抛出异常。
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit);
提交一个周期性任务,在给定的 initialDelay 之后首次启用,并在一次执行终止后的给定延迟之后进行下一次执行。 任务执行序列将无限期地继续下去,直到发生以下异常完成之一:
- 通过返回的 future 明确取消任务
- executor 终止,也会导致任务取消
- 任务执行引发异常。在这种情况下,调用返回的 future 的 get 方法将抛出 ExecutionException,保留异常作为其原因。
- 后续执行被抑制。返回的 future 的 isDone() 方法的后续调用将返回 true。
参数:
- command - 要执行的任务
- initialDelay - 首次执行的延迟时间
- delay - 一次执行终止后下一次执行的延迟时间
- unit - initialDelay 和 delay 参数的时间单位
返回:
- 代表重复任务系列未完成的 ScheduledFuture。future 的 get() 方法永远不会正常返回,在任务取消或任务执行异常终止时将抛出异常。
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,long initialDelay,long delay, TimeUnit unit);
示例
public class Task implements Runnable {
@Override
public void run() {
System.out.println("Task started");
}
}
public class CallableTask implements Callable<String> {
@Override
public String call() throws Exception {
return "Hello world";
}
}
public class ScheduledExecutorServiceDemo {
private Task runnableTask;
private CallableTask callableTask;
private void execute() {
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
getTasksToRun().apply(executorService);
//executorService.shutdown();
}
private void executeWithMultiThread() {
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
getTasksToRun().apply(executorService);
executorService.shutdown();
}
private Function<ScheduledExecutorService, Void> getTasksToRun() {
runnableTask = new Task();
callableTask = new CallableTask();
return (executorService -> {
Future<String> resultFuture = executorService.schedule(callableTask, 1, TimeUnit.SECONDS);
try {
System.out.println(resultFuture.get().toString());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
//executorService.scheduleAtFixedRate(runnableTask, 1, 5, TimeUnit.SECONDS);
executorService.scheduleWithFixedDelay( runnableTask, 1, 5, TimeUnit.SECONDS);
return null;
});
}
public static void main(String... args) throws InterruptedException {
ScheduledExecutorServiceDemo demo = new ScheduledExecutorServiceDemo();
demo.execute();
//demo.executeWithMultiThread();
Thread.sleep(10000);
}
}