码迷,mamicode.com
首页 > 编程语言 > 详细

JAVA随笔篇一(Timer源码分析和scheduleAtFixedRate的使用)

时间:2015-08-11 16:20:03      阅读:191      评论:0      收藏:0      [点我收藏+]

标签:java   定时器   timer类   scheduleatfixedrate   

写完了基础篇,想了很久要不要去写进阶篇,去写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();

TimerTask类实现了Runnable接口,待执行的任务置于run()中。在构造定时任务的时候,从TimerTask继承并实现run方法。并创建任务传给scheduleXXX方法。

sched方法中可以看出,sched方法中需要操作TaskQueue队列,而TimerThread线程启动之后同样使用这个队列,这就必须使用synchronized保证多线程安全使用。

2、scheduleXXX的使用:

Timer类的原理很简单,可以使用的函数不多,下面将全部列出。

(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的使用)

标签:java   定时器   timer类   scheduleatfixedrate   

原文地址:http://blog.csdn.net/feiyangtianyao/article/details/47403105

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!