ScheduleExecutorService接口中有四个重要的方法,其中scheduleAtFixedRate和scheduleWithFixedDelay在实现定时程序(每隔一段时间执行一次)时比较方便。
接口中四个方法如下:
该接口中前两个方法只会执行一次,后两个方法会定时循环执行。
— 三个方法简介—
1. ScheduledFuture<?> schedule(
Runnable command,
long delay,
TimeUnit unit
)
定义:在给定的延时之后,创建并执行一个启动一次性动作。
参数:
参数一(Runnable):命令执行的任务。
参数二(delay) :延迟执行的时间。
参数三(TimerUnit):延时蚕食的时间单位。
例:
在若依框架中,封装了一个异步打印日志的类,就是用到了schedule()方法:
public class AsyncManger{
// ··· ···
// 从ioc容器中获取 bean,注:SpringUtils也是若依框架封装的,通过名称来获取bean(可
// 以通过首字母小写形式根据名称来获取ioc容器中的bean)
private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
// 延迟20毫秒,执行任务类,在任务类中会去 insert 信息。
public viod execute(TimerTask task) {
executor.schedule(task, 20, TimeUnit.MILLISECONDS);
}
}
2. ScheduledFuture<?> scheduleAtFixedRate(
Runnable command,
long initialDelay,
long period,
TimeUnit unit
)
定义:创建并执行一个周期性的操作。
参数:
command:执行线程。
initialDelay:初始化延时。
period:两次开始执行最小间隔时间。
unit:计时单位。
3. ScheduledFuture<?> scheduleWithFixedDelay(
Runnable command,
long initialDelay,
long delay,
TimeUnit unit
)
定义:创建并执行一个周期性的操作。
参数:
command:执行线程。
initialDelay:初始化延时。
period:前一次执行结束到下一次执行开始的间隔时间(间隔执行延迟时间)。
unit:计时单位。
— 功能 —
1. 每隔多长时间重新执行一次任务。
初始延时0毫秒,每隔1000毫秒重新执行一次任务:
/**
* 以固定周期频率执行任务
*/
public class Test {
public static void main(String[] args) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
scheduledExecutorService.scheduleAtFixedRate(
Test.timerTask(), 0, 1000, TimeUnit.MILLISECONDS
);
}
public static TimerTask timerTask () {
return new TimerTask() {
@Override
public void run() {
System.out.println("执行了");
}
};
}
}
问题:
如果要执行的任务时间大于间隔时间,会如何处理呢?
其实当执行任务的时间大于我们指定的间隔时间时,它并不会在指定间隔时开辟一个新的线程并发执行这个任务,而是等待该线程执行完毕。
源码注释:
If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.
如果此任务的任何执行时间超过其周期,则后续执行可能开始较晚,但不会并发执行。
关于创建线程池:
创建一个线程池,该线程池可以调度命令在给定的延时后运行或定期执行。
参数:corePoolSize - 保持在池中的线程数,即使他们是空闲的。
返回:新创建的调度线程池。
抛出:如果corePoolSize < 0 ,IllegalArgumentException
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
关于 IllegalArgumentException 异常:
Illegal Argument Exception 非法参数异常。
2. 按照指定频率间隔执行某个任务。
初始化延时0ms开始,本次执行结束后延迟1000ms开始下次执行,注意:必须等到本次任务执行完毕才能开始延时且开始下一次任务执行。
/**
* 以固定延迟时间进行执行
* 本次任务执行完成后,需要延迟设定的延迟时间,才会执行新的任务
* 下边代码,延时0毫秒开始执行timerTask() 方法,Thread.sleep(2000) 暂停2000毫秒,之后才开始
* 延时1000毫秒,执行下一次任务。
*/
public class Test {
public static void main(String[] args) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
scheduledExecutorService.scheduleWithFixedDelay(
Test.timerTask(), 0, 1000, TimeUnit.MILLISECONDS
);
}
public static TimerTask timerTask () {
return new TimerTask() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("执行了");
}
};
}
}