java 源码解析:ScheduledThreadPoolExecutor和Timer

分析Timer

结合:
定时且周期性的任务研究I—Timer,进行分析:
使用Timer很简单,如下:

1
2
3
4
Timer timer = new Timer();
timer.schedule(new TimerTask(){
run(){实现run方法}
}, 1);

那么源码里面做了什么呢?

1
2
3
4
5
6
7
8
9
10
public Timer() {
this("Timer-" + serialNumber());
}
public Timer(String name) {
thread.setName(name);
thread.start();
}
//接着看声明的对象
private final TaskQueue queue = new TaskQueue();
private final TimerThread thread = new TimerThread(queue);

这里用到了TaskQueueTimerThread,接下来看这两个类
TaskQueue:(存储了TimerTask的队列)

1
private TimerTask[] queue = new TimerTask[128];

TimerTask implements Runnable这个就不多说。
类:TimerThreadTimer的内部类,也是继承一个线程,关注run方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
 public void run() {
try {
mainLoop();
} finally {
// Someone killed this Thread, behave as if Timer cancelled
synchronized(queue) {
newTasksMayBeScheduled = false;
queue.clear(); // Eliminate obsolete references
}
}
}
//核心方法
mainLoop(){...}//这里就不贴,自行参看

看下mainLoop做了什么

TimerThread中的mainLoop方法是核心,它会完成所有的任务执行,在一开始我们的队列为空,这时mainLoop方法调用wait()将会使线程进入等待状态,当我们使用schedule提交任务时会notify这个TimerThread线程若任务的执行未到则在wait相对的时间差

好,回到两个重要的调用方法:

1
2
timer.schedule(new TimerLongTask(),0, 3000);
timer.scheduleAtFixedRate(new TimerTask1(), 3000, 5000);

继续查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
public void schedule(TimerTask task, long delay) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
sched(task, System.currentTimeMillis()+delay, 0);
}
public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, System.currentTimeMillis()+delay, period);
}

都统一调用了sched的方法,我就看不到区别了(环境JDK7),从引用的文章里是这么说的:

重复执行scheduleAtFixedRate方法提交任务,主要是调用rescheduleMin方法对已经调用的任务进行重新设置调度延迟,并调用fixDown方法对队列里的任务根据延迟时间重新排序

好吧,看不出在哪里进行调用了。

分析ScheduledThreadPoolExecutor

查看:定时且周期性的任务研究II—ScheduledThreadPoolExecutor,这里从案例上讲解了客服了Timer的缺点的问题。涉及的知识多,日后再分析。