一、使用场景
ScheduledExcutorsService与TimerTask功能类似,都是为服务创建定时任务,间隔一定周期自动执行一次。
不同的是,TimerTask推荐用于单线程定时任务场景下。而ScheduledExcutorsService推荐在多线程定时任务下使用。原因是TimerTask在启动多个定时任务的情况下,若其中某个任务出现错误或异常,则该TimerTask启动的所有定时任务都会停止,而ScheduledExcutorsService则不会出现停止所有的情况。
二、ScheduledExcutorsService的实例化
在springBoot中想要使用ScheduledExcutorsService,需要先创建实例,并将该实例交给容器管理。创建实例的代码如下。
@Configuration
public class ScheduledExecutorConfig {
@Bean
public ScheduledExecutorService scheduledExecutorService() {
return new ScheduledThreadPoolExecutor(40, new
ThreadPoolExecutor.CallerRunsPolicy());
}
}
此处根据alibaba代码规范,推荐手动创建线程池(ScheduledThreadPoolExcutor)而不是通过Excutors创建线程池。原因是通过Excutors创建的线程池可能因任务过多或线程过多而出现OOM的错误。
三、ScheduledExcutorsService的使用
ScheduledExcutorsService类中包含4个方法,分别处理不同业务下的定时任务。
3.1 schedule(Runnable command, long delay, TimeUnit unit)
jdk源码中对该方法的描述为,该方法会创建并执行在给定延迟后启动的一次性操作,即在指定的延迟时间后该定时任务只会执行一次,后续不再执行。
参数说明:command(需要将具体业务代码在Runnable中实现,并作为参数传入)、
delay(指定定时任务的延迟启动时间)、
unit(delay的时间单位毫秒、秒....)。
@Component
public class ScheduleTest {
@Autowired
private ScheduledExecutorService scheduledExecutorService;
@PostConstruct
public void test() {
scheduledExecutorService.schedule(() -> {
xxxx // 具体的业务代码
}, 10, TimeUnit.SECONDS);
}
}
3.2 schedule(Callable<V> callable, long delay, TimeUnit unit)
public <V> ScheduledFuture<V> schedule(
Callable<V> callable, long delay, TimeUnit unit
);
该方法会创建并执行在给定延迟后启用的ScheduledFuture。该方法的参数为一个Callable函数,即该定时任务可取消或获取定时任务的执行结果。
参数与3.1类似,不再做解释。
@Component
public class ScheduleTest {
@Autowired
private ScheduledExecutorService scheduledExecutorService;
@PostConstruct
public void test() {
try {
ScheduledFuture<String> schedule = scheduledExecutorService.schedule(new MyThread4(), 10, TimeUnit.SECONDS);
// 获取定时任务的执行结果
String s = schedule.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
class MyThread4 implements Callable<String> {
@Override
public String call() throws Exception {
return "Callable !!";
}
}
}
3.3 scheduleAtFixedRate(Runnable command, long delay, long period, TimeUnit unit)
该方法会创建并执行一个定期操作,该操作会在给定的延迟后启用,随后在给定的时间段内再次启用。即该定时任务是会重复执行的定时任务,且在执行时间过长超过执行周期时,下一次任务会延迟开始,不会与当前任务同时进行。当遇到异常时则会禁止后续执行。
参数说明:period(两次任务中间的间隔时间)
@Component
public class ScheduleTest {
@Autowired
private ScheduledExecutorService scheduledExecutorService;
@PostConstruct
public void test() {
scheduledExecutorService.scheduleAtFixedRate(() -> {
xxxxx // 具体的业务代码
}, 10, 20, TimeUnit.SECONDS);
}
}
3.4 scheduleWithFixedDelay(Runnable command, long delay, long period, TimeUnit unit)
该方法与3.3方法类似,区别是无论当前任务执行时间的长短,会按照指定的延迟时间执行下一次任务。例如:任务间隔时间为10s,第一次任务执行了5s,则下一次任务的执行时间为第15s;若第一次执行了20s,则第二次的执行时间为第30s。
参数与3.3相同,不做说明。
@Component
public class ScheduleTest {
@Autowired
private ScheduledExecutorService scheduledExecutorService;
@PostConstruct
public void test() {
scheduledExecutorService.scheduleWithFixedDelay(() -> {
xxxxx // 具体的业务代码
}, 10, 20, TimeUnit.SECONDS);
}
}
以上就是ScheduledExcutorsService的四种用法。