在前面一篇Executor执行框架源代码分析(三)中,已经详细介绍了ThreadPoolExecutor的实现方式。ScheduledThreadPoolExecutor是ThreadPoolExecutor的子类,其扩展了ThreadPoolExecutor的功能,扩展的功能主要是用来执行周期性任务的。ScheduledThreadPoolExecutor的任务分为三类:
1、单一延时任务。设定一个时间,10s。任务将会在提交10秒钟后运行。
2、固定周期任务。提交一个任务,设定好周期period时间,如,3秒。任务将会每3秒被调用一次,如果任务的执行时间超过了3秒,那么将会在任务执行完之后立即进行再次调用,不会进行并发执行。
3、周期延时任务。提交一个任务,设置后固定延时时间,如,3秒。任务将会在第一次任务结束之后,延时3秒钟再次调用任务任务第二次。依次类推,第二次调用结束后,延时3秒钟,进行第三次调用。
先看一个demo,感受一下ScheduledThreadPoolExecutor的使用:
public class TestMain02 {
public static void main(String[] args) throws Exception{
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2); //创建一个ScheduleThreadPool
//周期延时任务,以固定的延时运行任务。参数分别是:
//task对象,第一次调用的延时时间(2秒),后续任务调用的延时时间(3秒),延时时间的单位:秒
executor.scheduleWithFixedDelay(new Task(), 2,3, TimeUnit.SECONDS);
}
}
public class Task implements Runnable{
@Override
public void run() {
try {
System.out.println(this+" 被线程 "+Thread.currentThread().getName()+" 执行!!,开始时间:"+new Date());
Thread.sleep(4000);
System.out.println(this+" 被线程 "+Thread.currentThread().getName()+" 执行!!,结束时间: "+new Date());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//执行结果
//com.thread.blog.Task@534f5d93 被线程 pool-1-thread-1 执行!!,开始时间:Mon Mar 12 10:46:48 CST 2018
//com.thread.blog.Task@534f5d93 被线程 pool-1-thread-1 执行!!,结束时间: Mon Mar 12 10:46:52 CST 2018 (第一次调用结束)
//com.thread.blog.Task@534f5d93 被线程 pool-1-thread-1 执行!!,开始时间:Mon Mar 12 10:46:55 CST 2018 (3秒钟之后,第二次调用开始)
//com.thread.blog.Task@534f5d93 被线程 pool-1-thread-1 执行!!,结束时间: Mon Mar 12 10:46:59 CST 2018
//如果不关闭executor执行器,会一直按照上面的形式进行输出
上面调用的是scheduleWithFixedDelay方法,这个方法将会以固定的延时时间执行任务。类似的方法还有:
1、schedule(Runnable command,long delay, TimeUnit unit),提交后延迟执行,延迟时间:delay;
2、scheduleAtFixedRate(Runnable command, long initialDelay,long delay, TimeUnit unit), 提交后延迟执行,第一次延迟时间:initialDelay。后续任务将会以{initialDelay + delay},{initialDelay + delay*2}……进行执行。即上文所说的“固定周期任务”。
一、schedule方法的实现