美文网首页
Timer源码详解

Timer源码详解

作者: 陈萍儿Candy | 来源:发表于2020-11-27 15:31 被阅读0次

    Timer:线程调度任务以便将来在后台线程中执行的一种工具。任务可以安排为一次性执行,也可以安排为定期重复执行。

    1.schedule(TimerTask task, long delay)方法

    /**
         * Schedules the specified task for execution after the specified delay.
         *
         * @param task  task to be scheduled.
         * @param delay delay in milliseconds before task is to be executed.
         * @throws IllegalArgumentException if <tt>delay</tt> is negative, or
         *         <tt>delay + System.currentTimeMillis()</tt> is negative.
         * @throws IllegalStateException if task was already scheduled or
         *         cancelled, timer was cancelled, or timer thread terminated.
         * @throws NullPointerException if {@code task} is null
         */
        public void schedule(TimerTask task, long delay) {
            if (delay < 0)
                throw new IllegalArgumentException("Negative delay.");
            sched(task, System.currentTimeMillis()+delay, 0);
        }
    

    一般我们调用schedule方法后,为什么TimerTask的run方法中的代码是在自线程中执行?
    1.Timer中有一个线程,

    /**
         * The timer thread.
         */
        // Android-added: @ReachabilitySensitive
        @ReachabilitySensitive
        private final TimerThread thread = new TimerThread(queue);
    

    当我们new Timer创建对象时,会开启这个线程

    public Timer(String name) {
            thread.setName(name);
            thread.start();
        }
    

    2.Timer中有一个 TaskQueue,是存放TimerTask的类,里面是数组存储

    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];// TimerTask数组存储
    
        /**
         * The number of tasks in the priority queue.  (The tasks are stored in
         * queue[1] up to queue[size]).
         */
        private int size = 0;
    
        /**
         * Returns the number of tasks currently on the queue.
         */
        int size() {
            return size;
        }
    
        /**
         * Adds a new task to the priority queue.
         */
        void add(TimerTask task) {
            // Grow backing store if necessary
            if (size + 1 == queue.length)
                queue = Arrays.copyOf(queue, 2*queue.length);
    
            queue[++size] = task;
            fixUp(size);
        }
    ....(后面还有很多代码)
    
    }
    

    3.线程中的run中mainLoop的方法如下,new Timer对象后,queue队列没有task,释放queue锁,进入阻塞状态????,

    
        /**
         * The main timer loop.  (See class comment.)
         */
        private void mainLoop() {
            while (true) {
                try {
                    TimerTask task;
                    boolean taskFired;
                    synchronized(queue) {
                        // Wait for queue to become non-empty
                        while (queue.isEmpty() && newTasksMayBeScheduled)
                            queue.wait();
                        if (queue.isEmpty())
                            break; // Queue is empty and will forever remain; die
    
                        // Queue nonempty; look at first evt and do the right thing
                        long currentTime, executionTime;
                        task = queue.getMin();
                        synchronized(task.lock) {
                            if (task.state == TimerTask.CANCELLED) {
                                queue.removeMin();
                                continue;  // No action required, poll queue 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);
                                }
                            }
                        }
                        if (!taskFired) // Task hasn't yet fired; wait
                            queue.wait(executionTime - currentTime);
                    }
                    if (taskFired)  // Task fired; run it, holding no locks
                        task.run();
                } catch(InterruptedException e) {
                }
            }
        }
    }
    

    当我们在调用Timer中的schedule方法时,是先把TimerTask加入到taskQueue中,并唤醒锁是queue的TimerThread,执行TimerTask中的run方法,所以TimerTask中的run方法是在子线程执行的。

        private void sched(TimerTask task, long time, long period) {
            if (time < 0)
                throw new IllegalArgumentException("Illegal execution time.");
    
            // Constrain value of period sufficiently to prevent numeric
            // overflow while still being effectively infinitely large.
            if (Math.abs(period) > (Long.MAX_VALUE >> 1))
                period >>= 1;
    
            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();
            }
        }
    

    相关文章

      网友评论

          本文标题:Timer源码详解

          本文链接:https://www.haomeiwen.com/subject/jgdziktx.html