Timer 定时器原理:
Timer 类:
if (time < 0)
thrownew IllegalArgumentException("Illegal executiontime.");
// Constrain value of periodsufficiently to prevent numeric
// overflow while still beingeffectively infinitely large.
if (Math.abs(period) >(Long.MAX_VALUE >> 1))
period >>= 1;
synchronized(queue) {
if (!thread.newTasksMayBeScheduled)
thrownew IllegalStateException("Timer alreadycancelled.");
synchronized(task.lock) {
if (task.state != TimerTask.VIRGIN)
thrownew IllegalStateException(
"Task already scheduledor cancelled");
task.nextExecutionTime = time;
task.period = period;
task.state = TimerTask.SCHEDULED;
}
queue.add(task);
if (queue.getMin() == task)
queue.notify();
}
TimerTask:
package java.util;
public abstract class TimerTask implementsRunnable {
final Object lock = new Object(); //锁
int state = VIRGIN;
static final int VIRGIN = 0;
static final int SCHEDULED = 1;
static final int EXECUTED = 2;
static final int CANCELLED = 3;
long nextExecutionTime;
long period = 0;
protected TimerTask() {
}
public abstract void run();
public boolean cancel() {
synchronized(lock) {
boolean result = (state == SCHEDULED);
state = CANCELLED;
return result;
}
}
public long scheduledExecutionTime() {
synchronized(lock) {
return (period < 0 ? nextExecutionTime +period
: nextExecutionTime - period);
}
}
}
TaskQueue:任务队列
Public class TaskQueue{
private TimerTask[] queue = new TimerTask[128];
privateintsize = 0;
int size() {
returnsize;
}
void add(TimerTask task) {
// Grow backing store ifnecessary
if (size + 1 == queue.length)
queue = Arrays.copyOf(queue, 2*queue.length);
queue[++size] = task;
fixUp(size);
}
TimerTask getMin() {
returnqueue[1];
}
TimerTask get(int i) {
returnqueue[i];
}
void removeMin() {
queue[1] = queue[size];
queue[size--] = null;
fixDown(1);
}
void quickRemove(int i) {
assert i <= size;
queue[i] = queue[size];
queue[size--] = null; }
void rescheduleMin(long newTime) {
queue[1].nextExecutionTime = newTime;
fixDown(1);
}
boolean isEmpty() {
returnsize==0;
}
void clear() {
for (int i=1; i<=size; i++)
queue[i] = null;
size = 0;
}
privatevoid fixUp(int k) {
while (k > 1) {
int j = k >> 1;
if (queue[j].nextExecutionTime <= queue[k].nextExecutionTime)
break;
TimerTask tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp;
k = j;
}
}
privatevoid fixDown(int k) {
int j;
while ((j = k << 1) <= size && j > 0) {
if (j < size &&
queue[j].nextExecutionTime > queue[j+1].nextExecutionTime)
j++; // j indexes smallest kid
if (queue[k].nextExecutionTime <= queue[j].nextExecutionTime)
break;
TimerTask tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp;
k = j;
}
}
void heapify() {
for (int i = size/2; i >= 1; i--)
fixDown(i);
}
TimerThread: 定时任务线程
Public TimerThread{
booleannewTasksMayBeScheduled = true;
private TaskQueue queue;
TimerThread(TaskQueue queue) {
this.queue = queue;
}
publicvoid run() {
try {
mainLoop();
} finally {
synchronized(queue) {
newTasksMayBeScheduled = false;
queue.clear(); }
}
}
privatevoid mainLoop() {
while (true) {
try {
TimerTask task;
boolean taskFired;
synchronized(queue) {
while (queue.isEmpty() && newTasksMayBeScheduled)
queue.wait();
if (queue.isEmpty())
break;
long currentTime, executionTime;
task = queue.getMin();
synchronized(task.lock) {
if (task.state == TimerTask.CANCELLED) {
queue.removeMin();
continue;
}
currentTime = System.currentTimeMillis();
executionTime = task.nextExecutionTime;
if (taskFired =(executionTime<=currentTime)) {
if (task.period == 0) { // Non-repeating, remove
queue.removeMin();
task.state = TimerTask.EXECUTED;
} else { queue.rescheduleMin(
task.period<0 ? currentTime - task.period
: executionTime + task.period);
}
}
}
if (!taskFired) queue.wait(executionTime -currentTime);
}
if (taskFired) task.run();
} catch(InterruptedException e) {
}
}
}
}
Timer是一个单线程 + 最小堆 + 不断轮询
Timer time=newTimer();
n 调用构造方法创建timer类
public Timer(){
this("Timer-"+ serialNumber());
}
private final static AtomicIntegernextSerialNumber = new AtomicInteger(0);
private static int serialNumber() {
return nextSerialNumber.getAndIncrement();
}
This方法: 这个name是Timer-0
public Timer(String name) {
thread.setName(name);
thread.start();
}
对name设置值
public final void setName(String name) {
checkAccess();
this.name = name.toCharArray();
}
checkAccess();
这个是权限控制
publicfinalvoid checkAccess() {
SecurityManager security =System.getSecurityManager();
if (security != null) {
security.checkAccess(this);
}
}
SecurityManager 对运行的java代码进行权限控制,防止恶意代码的运行
开启线程:
thread.start(); 这个运行的是timerThread 的run方法
这里先略过,
time.schedule(new TaskTest(), 1000); 定时类设置任务和每次时间间隔执行的时间
public void schedule(TimerTask task, long delay){
if (delay < 0)
throw new IllegalArgumentException("Negativedelay.");
sched(task, System.currentTimeMillis()+delay, 0);
}
//初始化task、 task 执行任务 time时间period 间隔
privatevoid sched(TimerTask task, long time, long period) {
if (time < 0)
thrownew IllegalArgumentException("Illegal executiontime.");
// Constrain value of periodsufficiently to prevent numeric
// overflow while still beingeffectively infinitely large.
if (Math.abs(period) >(Long.MAX_VALUE >> 1)) 间隔的绝对值 大于 LONG的最大值右移动一位 Long.MAX_VALUE =9223372036854775807
Long.MAX_VALUE >> 1 =4611686018427387903
period >>= 1; period右移一位并重新赋值给自己
这里插一下开始的时候创建了thread TimerThread thread = new TimerThread(queue);
Queue private TimerTask[] queue = newTimerTask[128];
synchronized(queue) {
if (!thread.newTasksMayBeScheduled) 判断 线程的newTasksMayBeScheduled 这个值是true还是false
thrownew IllegalStateException("Timer alreadycancelled.");如果是true 就报错
synchronized(task.lock) {
if (task.state != TimerTask.VIRGIN) 判断线程状态 task。State 初始是0 TimerTask.VIRGIN 初始也是0,如果初始状态不等就报错
thrownew IllegalStateException("Task already scheduledor cancelled");
task.nextExecutionTime = time; 任务的下一个执行时间是time
task.period = period; 间隔是period
task.state = TimerTask.SCHEDULED; TimerTask.SCHEDULED =1
}
queue.add(task); 把任务加入到队列
这里插入一下queue的方法add
void add(TimerTask task) {
// Grow backing store if necessary
if (size + 1 == queue.length) size 初始化是0 ,如果size+1是现在队列的长度就默认扩容2倍
queue = Arrays.copyOf(queue, 2*queue.length);
queue[++size] = task; 加入队列 queue是TimerTask数组,默认初始化128内存
fixUp(size);
这里插入fixup 比较队列中现在这个任务和上一个任务的执行时间
privatevoidfixUp(int k) {
while (k> 1) {
int j =k >> 1; 右移动是减少 2>>1 变成1
if (queue[j].nextExecutionTime<= queue[k].nextExecutionTime)
break;
TimerTask tmp = queue[j]; queue[j] = queue[k]; queue[k] =tmp;
k = j; 这里把k减少
}
}
}
if (queue.getMin() == task) 如果队列中的 和现在这个task一样 就唤醒其他等待线程
getMIn=queue【1】;
queue.notify();
}
}
、task的执行:
publicvoidrun() {
try {
mainLoop();
} finally {
// Someonekilled this Thread, behave as if Timer cancelled
synchronized(queue) {
newTasksMayBeScheduled = false;
queue.clear(); // Eliminate obsoletereferences
}
}
}
privatevoidmainLoop() {
while (true) { //轮循环
try {
TimerTask task;
booleantaskFired;
synchronized(queue) {
// Wait forqueue to become non-empty
while (queue.isEmpty()&& newTasksMayBeScheduled) 如果队列是空的就进入等待
queue.wait();
if (queue.isEmpty())
break; //Queue is empty and will forever remain; die
// Queuenonempty; look at first evt and do the right thing
longcurrentTime, executionTime;
task = queue.getMin();
synchronized(task.lock) {
if(task.state == TimerTask.CANCELLED) {
queue.removeMin();
continue; // No action required, pollqueue again
}
currentTime = System.currentTimeMillis();
executionTime = task.nextExecutionTime;
if(taskFired = (executionTime<=currentTime)) { //比较执行时间和系统时间
if(task.period == 0) { //Non-repeating, remove
queue.removeMin();
task.state =TimerTask.EXECUTED;
} else { //Repeating task, reschedule
queue.rescheduleMin(
task.period<0? currentTime - task.period
: executionTime + task.period); //这里计算下一次的执行时间,轮询的时候比较下一次的执行时间,如果时间不对就不执行 这里有个问题,就是为什么动态循环都是只有下下一次才能改变这个时间间隔,而不是下一次,因为这次就决定了下次时间的决定。所以timer没办法改变下一次的执行时间,但是可以改变下下次的执行,那么这里我是不是可以重写这个函数,把执行时间可以从外部传进去。
}
}
}
if(!taskFired) // Task hasn't yet fired; wait
queue.wait(executionTime- currentTime);
}
if(taskFired) // Task fired;run it, holding no locks
task.run();
} catch(InterruptedExceptione) {
}
}
}