zoukankan      html  css  js  c++  java
  • 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类的原理非常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 结束!");
            }
    }



  • 相关阅读:
    operation not possible due to RF-kill
    kali linux karmetasploit配置【续】
    kali linux karmetasploit配置
    转 15款免费WiFi(入侵破解)安全测试工具
    利用NTFS交换数据流隐藏文件
    droidbox官网
    Linux安装IDA神器
    Linksys WRT120N路由器备份文件解析
    设置主机只对网关的报文进行响应
    MySQL无法存储emoji表情方案
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/6960997.html
Copyright © 2011-2022 走看看