ScheduledThreadPoolExecutor详解
ScheduledThreadPoolExecutor 延迟或定时任务执行线程池
ScheduledThreadPoolExecutor主要用来在给定的延迟之后运行任务,或者定期执行任务。
ScheduledThreadPoolExecutor的功能与Timer类似,但 ScheduledThreadPoolExecutor功能更强大、更灵活。
Timer对应的是单个后台线程,而ScheduledThreadPoolExecutor可以在构造函数中指定多个对应的后台线程数。
ScheduledThreadPoolExecutor还提供了非常灵活的API,用于执行任务。
其任务的执行策略主要分为两大类:
- 在一定延迟之后只执行一次某个任务;
- 在一定延迟之后周期性的执行某个任务。
//延迟delay时间后,执行command任务一次
public ScheduledFuture<?> schedule(Runnable command,long delay,TimeUnit unit) {}
//延迟delay时间后,执行callable任务一次,返回值为V
public <V> ScheduledFuture<V> schedule(Callable<V> callable,long delay,TimeUnit unit) {}
//延迟initialDelay时间后开始第1次执行,预计第n次执任务的时间等于首次开始执行时间+period*(n-1)(n>0,每次加1),预计第n次执任务时间>=上次结束时间,则按预计第n次执任务时间执行任务,反之则按上次结束时间实行任务
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit) {}
//延迟initialDelay时间后,第一次执行command任务,上次执行command任务终止后,延迟delay时间,再次执行command任务
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit) {}
public class ScheduledTest {
static int i=1;
public static void main(String[] args) {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
System.out.println("开始执行定时任务:" + new Date());
//延迟initialDelay时间后,第一次执行command任务,如果上一次任务执行完毕后,其执行时间大于等于period,则选择在上个任务开始时间+period的倍数之后执行下个任务,如果上次任务执行完毕后,其执行时间小于period,则选择在上个任务开始时间+period之后执行下个任务。
executor.scheduleAtFixedRate(()->{
System.out.println("第"+i+"次 beginTime:" + new Date());
try {
if (i<5){
Thread.sleep(i*1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("第"+i+"次 endTime:" + new Date());
i++;
},1,2, TimeUnit.SECONDS);
}
}
//执行结果:
//开始执行任务定时任务 和 第一次执行任务之间 间隔initialDelay时间 这里设置1秒
开始执行定时任务:Sun Aug 06 11:39:55 CST 2023
第1次 beginTime:Sun Aug 06 11:39:56 CST 2023
第1次 endTime:Sun Aug 06 11:39:57 CST 2023
//预计下次开始执行时间为首次开始执行时间(11:39:56)+period(2秒)*的倍数(此处1倍)之后的时间(11:39:58)。预计下次开始执行时间>=本次结束时间(11:39:57),则下次执行开始时间为预计下次开始执行时间(11:39:58)
第2次 beginTime:Sun Aug 06 11:39:58 CST 2023
第2次 endTime:Sun Aug 06 11:40:00 CST 2023
//预计下次开始执行时间为首次开始执行时间(11:39:56)+period(2秒)*的倍数(此处2倍)之后的时间(11:40:00)。预计下次开始执行时间>=本次结束时间(11:40:00),则下次执行开始时间为预计下次开始执行时间(11:40:00)
第3次 beginTime:Sun Aug 06 11:40:00 CST 2023
第3次 endTime:Sun Aug 06 11:40:03 CST 2023
//预计下次开始执行时间为首次开始执行时间(11:39:56)+period(2秒)*的倍数(此处3倍)之后的时间(11:40:02)。预计下次开始执行时间<本次结束时间(11:40:03),则下次执行开始时间为本次结束时间(11:40:03)
第4次 beginTime:Sun Aug 06 11:40:03 CST 2023
第4次 endTime:Sun Aug 06 11:40:07 CST 2023
//预计下次开始执行时间为首次开始执行时间(11:39:56)+period(2秒)*的倍数(此处4倍)之后的时间(11:40:04)。预计下次开始执行时间<本次结束时间(11:40:07),则下次执行开始时间为本次结束时间(11:40:07)
第5次 beginTime:Sun Aug 06 11:40:07 CST 2023
第5次 endTime:Sun Aug 06 11:40:07 CST 2023
//预计下次开始执行时间为首次开始执行时间(11:39:56)+period(2秒)*的倍数(此处5倍)之后的时间(11:40:06)。预计下次开始执行时间<本次结束时间(11:40:07),则下次执行开始时间为本次结束时间(11:40:07)
第6次 beginTime:Sun Aug 06 11:40:07 CST 2023
第6次 endTime:Sun Aug 06 11:40:07 CST 2023
//预计下次开始执行时间为首次开始执行时间(11:39:56)+period(2秒)*的倍数(此处6倍)之后的时间(11:40:08)。预计下次开始执行时间>=本次结束时间(11:40:07),则下次执行开始时间为预计下次开始执行时间(11:40:08)
第7次 beginTime:Sun Aug 06 11:40:08 CST 2023
第7次 endTime:Sun Aug 06 11:40:08 CST 2023
//预计下次开始执行时间为首次开始执行时间(11:39:56)+period(2秒)*的倍数(此处7倍)之后的时间(11:40:10)。预计下次开始执行时间>=本次结束时间(11:40:08),则下次执行开始时间为预计下次开始执行时间(11:40:10)
第8次 beginTime:Sun Aug 06 11:40:10 CST 2023
第8次 endTime:Sun Aug 06 11:40:10 CST 2023
//预计下次开始执行时间为首次开始执行时间(11:39:56)+period(2秒)*的倍数(此处8倍)之后的时间(11:40:12)。预计下次开始执行时间>=本次结束时间(11:40:10),则下次执行开始时间为预计下次开始执行时间(11:40:12)
第9次 beginTime:Sun Aug 06 11:40:12 CST 2023
第9次 endTime:Sun Aug 06 11:40:12 CST 2023
//预计下次开始执行时间为首次开始执行时间(11:39:56)+period(2秒)*的倍数(此处9倍)之后的时间(11:40:14)。预计下次开始执行时间>=本次结束时间(11:40:12),则下次执行开始时间为预计下次开始执行时间(11:40:14)
第10次 beginTime:Sun Aug 06 11:40:14 CST 2023
第10次 endTime:Sun Aug 06 11:40:14 CST 2023
Process finished with exit code -1
public class ScheduledTest {
static int i=1;
public static void main(String[] args) {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2);
延迟initialDelay时间后,第一次执行command任务,上次执行command任务终止后,延迟delay时间,再次执行command任务
executor.scheduleWithFixedDelay(()->{
System.out.println(new Date());
try {
Thread.sleep(i*1000);
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
},1,5, TimeUnit.SECONDS);
}
}
// 执行结果
Sun Aug 06 10:48:53 CST 2023
Sun Aug 06 10:48:59 CST 2023
Sun Aug 06 10:49:06 CST 2023
Sun Aug 06 10:49:14 CST 2023
Sun Aug 06 10:49:23 CST 2023
Sun Aug 06 10:49:33 CST 2023
Sun Aug 06 10:49:44 CST 2023
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), threadFactory);
}
public ScheduledThreadPoolExecutor(int corePoolSize,
RejectedExecutionHandler handler) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), handler);
}
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), threadFactory, handler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}