背景
Timer的优点在于简单易用,但是由于所有的任务都是由同一个线程来调度,因此所有的任务都是串行执行的,同一时间只能有一个任务在执行,在前一个任务的延时都会影响到之后的任务。同时,Timer不会捕获TimerTask的异常,只是简单的停止,这样也肯定会影响到之后任务的执行。当然可以为了完成多线程适应多个Timer,只是这些Timer需要自己来管理,而不是一个框架体系。
鉴于Timer的上述缺陷,Java5推出了基于线程池设计的ScheduledThreadPoolExecutor。其设计思想是,每一个被调度的任务都会由线程池中的一个线程去执行,因此任务是并发的,相互之间不会有干扰。
而且,只有当任务的执行时间到来时,ScheduledThreadPoolExecutor才会真正的启动一个线程,其余时间ScheduledThreadPoolExecutor都是在轮询任务的状态。
Java中的ScheduledThreadPoolExecutor类
我们先来看一下ScheduledThreadPoolExecutor类的具体实现源码。
public class ScheduledThreadPoolExecutor
extends ThreadPoolExecutor
implements ScheduledExecutorService {
...
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,
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);
}
}
发现ScheduledThreadPoolExecutor是继承于ThreadPoolExecutor,并且实现了ScheduledExecutorService接口,其中构
造方法为调用了父类ThreadPoolExecutor类的构造方法,只不过是阻塞队列变为了DelayedWorkQueue,而不是
ThreadPoolExecutor默认的LinkedBlockingQueue。关于DelayedWorkQueue,我们后面在说。
ThreadPoolExecutor不用多说,下面我们看看ScheduledExecutorService接口,源码如下:
public interface ScheduledExecutorService extends ExecutorService {
public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);
public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay, TimeUnit unit);
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);
}
看起来和ThreadPoolExecutor类结构很类似。ScheduledExecutorService接口继承了ExecutorService接口,该接
口中主要定义了一些线程池状态管理的一些方法。下面来看看该接口中定义的4个方法,和Timer中的方法类似,大概可以猜到
其实就是和任务调度有关的方法。其中第一个方法和第二个方法区别不大,一个传入Runnable,一个传入Callable,大家对