标签:binary 变量 cancel xxx 多线程安全 structure start tracking gettime
写完了基础篇,想了非常久要不要去写进阶篇。去写JSP等等的用法。最后决定先不去写。由于自己并非JAVA方面的大牛。眼下也在边做边学,所以决定先将自己不懂的拿出来学并记下来。
Timer是Java自带的java.util.Timer类,通过调度一个java.util.TimerTask任务。这样的方式能够让程序依照某一个频度运行。
1、Timer类的源代码分析:
public class Timer { /** * The timer task queue. This data structure is shared with the timer * thread. The timer produces tasks, via its various schedule calls, * and the timer thread consumes, executing timer tasks as appropriate, * and removing them from the queue when they‘re obsolete. */ private TaskQueue queue = new TaskQueue(); /** * The timer thread. */ private TimerThread thread = new TimerThread(queue);首先Timer类定义了两个私有变量TaskQueue和TimerThread。
TaskQueue:Timer类定义了一个定时器任务队列。一个TimerTasks的优先级队列。
class TaskQueue { /** * Priority queue represented as a balanced binary heap: the two children * of queue[n] are queue[2*n] and queue[2*n+1]. The priority queue is * ordered on the nextExecutionTime field: The TimerTask with the lowest * nextExecutionTime is in queue[1] (assuming the queue is nonempty). For * each node n in the heap, and each descendant of n, d, * n.nextExecutionTime <= d.nextExecutionTime. */ private TimerTask[] queue = new TimerTask[128];
TimerThread:Timer类的任务运行线程。从Thread类继承。以TaskQueue为參数。
在使用Timer类,首先new一个Timer对象,然后利用scheduleXXX函数运行任务,首先分析Timer对象构造过程:
public Timer() { this("Timer-" + serialNumber()); }
public Timer(boolean isDaemon) { this("Timer-" + serialNumber(), isDaemon); }<span style="white-space:pre"> </span>
public Timer(String name) { thread.setName(name); thread.start(); }
public Timer(String name, boolean isDaemon) { thread.setName(name); thread.setDaemon(isDaemon); thread.start(); }能够看出,Timer在构造对象过程中,须要启动一个TimerThread线程,因此能够推測,TimerThread线程和Timer对象共同维护一个TaskQueue,利用TaskQueue进行信息传递。
接下来看scheduleXXX函数。全部的scheduleXXX函数都须要调用sched方法,
private void sched(TimerTask task, long time, long period) { if (time < 0) throw new IllegalArgumentException("Illegal execution time."); synchronized(queue) { if (!thread.newTasksMayBeScheduled) throw new IllegalStateException("Timer already cancelled."); synchronized(task.lock) { if (task.state != TimerTask.VIRGIN) throw new IllegalStateException( "Task already scheduled or cancelled"); task.nextExecutionTime = time; task.period = period; task.state = TimerTask.SCHEDULED; } queue.add(task); if (queue.getMin() == task) queue.notify(); } }这里首先介绍一下TimerTask类:
public abstract class TimerTask implements Runnable { /** * This object is used to control access to the TimerTask internals. */ final Object lock = new Object();
从sched方法中能够看出,sched方法中须要操作TaskQueue队列,而TimerThread线程启动之后相同使用这个队列,这就必须使用synchronized保证多线程安全使用。
2、scheduleXXX的使用:
Timer类的原理非常easy,能够使用的函数不多。以下将所有列出。
(1)void java.util.Timer.schedule(TimerTask task, long delay):多长时间(毫秒)后运行任务
(2)void java.util.Timer.schedule(TimerTask task, Date time):设定某个时间运行任务
(3)void java.util.Timer.schedule(TimerTask task, long delay, long period):delay时间后開始运行任务,并每隔period时间调用任务一次。
(4)void java.util.Timer.schedule(TimerTask task, Date firstTime, long period):第一次在指定firstTime时间点运行任务,之后每隔period时间调用任务一次。
(5)void java.util.Timer.scheduleAtFixedRate(TimerTask task, long delay, long period):delay时间后開始运行任务。并每隔period时间调用任务一次。
(6)void java.util.Timer.scheduleAtFixedRate(TimerTask task, Date firstTime, long period):第一次在指定firstTime时间点运行任务。之后每隔period时间调用任务一次。
(7)void java.util.Timer.cancel():终止该Timer
(8)boolean java.util.TimerTask.cancel():终止该TimerTask
这些scheduleXXX方法中,除了(1)(2)外,其它都能够反复调用任务,基本的区别就是schedule和scheduleAtFixedRate的区别。
schedule()方法更注重保持间隔时间的稳定:保障每隔period时间可调用一次。
scheduleAtFixedRate()方法更注重保持运行频率的稳定:保障多次调用的频率趋近于period时间。假设某一次调用时间大于period,下一次就会尽量小于period。以保障频率接近于period
3、Timer类的使用示列
首先创建一个任务:
<pre name="code" class="java">import java.util.TimerTask; public class MyTask extends TimerTask{ private int id; public MyTask(int id){ this.id = id; } public void run(){ System.out.println("线程" + id + ":正在运行"); //System.gc(); } }main函数代码:
import java.util.Date; import java.util.Timer; public class Test{ public static void main(String[] args){ Timer timer = new Timer(); timer.schedule(new MyTask(1), 5000);// 5秒后启动任务 MyTask secondTask = new MyTask(2); timer.schedule(secondTask, 1000, 3000); // 1秒后启动任务,以后每隔3秒运行一次线程 Date date = new Date(); timer.schedule(new MyTask(3), new Date(date.getTime() + 1000)); // 以date为參数,指定某个时间点运行线程 // timer.cancel(); // secondTask.cancel(); System.out.println("main thread 结束!"); } }
JAVA随笔篇一(Timer源代码分析和scheduleAtFixedRate的使用)
标签:binary 变量 cancel xxx 多线程安全 structure start tracking gettime
原文地址:http://www.cnblogs.com/zsychanpin/p/6960997.html