Timer源码剖析

1、Timer概述

Timer类我们通常用来执行延迟、定时任务,与其密切相关的类有TimerTask、TaskQueue、TimerThread。与Android的消息机制类似,timer.schedule()不断的将任务扔到TaskQueue中,TimerThread用于不断的循环任务队列执行任务。

人傻话少,裁剪别人写的。

170555_quuI_3342652.png

2、任务的执行顺序是否和代码中写的一致?

private void sched(TimerTask task, long time, long period) {
    if (time < 0) throw new IllegalArgumentException("Illegal execution time.");
    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();
    }
}

当一个任务加到队列中时加了锁,所以多次执行schedule( )代码添加任务,Timer并不能保证任务执行的先后顺序是按照代码中写的顺序。

public class JavaMain {
    public static void main(String[] args) {
        Timer timer = new Timer();
        timer.schedule(new Task(1), 0);
        timer.schedule(new Task(2), 0);
        timer.schedule(new Task(3), 0);
        timer.schedule(new Task(4), 0);
        timer.schedule(new Task(5), 0);
        timer.schedule(new Task(6), 0);
        timer.schedule(new Task(7), 0);
    }

    static class Task extends TimerTask {
        private int index = 0;

        Task(int i) {
            index = i;
        }

        @Override
        public void run() {
            System.out.println("hell world! = " + index);
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

执行结果:

hell world! = 1
hell world! = 7
hell world! = 6
hell world! = 5
hell world! = 4
hell world! = 3
hell world! = 2

113034_tlpf_3342652.png

3、源码分析

// 用于创建任务
public class Timer {

    private final TaskQueue queue = new TaskQueue();
    private final TimerThread thread = new TimerThread(queue);

    // 以自增形式,标记任务名称
    private final static AtomicInteger nextSerialNumber = new AtomicInteger(0);

    private static int serialNumber() {
        return nextSerialNumber.getAndIncrement();
    }

    public Timer() {
        this("Timer-" + serialNumber());
    }

    public Timer(boolean isDaemon) {
        this("Timer-" + serialNumber(), isDaemon);
    }

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

    /**
     * 是否守护线程
     *
     * @param name
     * @param isDaemon
     */
    public Timer(String name, boolean isDaemon) {
        thread.setName(name);
        thread.setDaemon(isDaemon);
        thread.start();
    }

    public void schedule(TimerTask task, long delay) {
        if (delay < 0)
            throw new IllegalArgumentException("Negative delay.");
        sched(task, System.currentTimeMillis() + delay, 0);
    }

    public void schedule(TimerTask task, Date time) {
        sched(task, time.getTime(), 0);
    }

    public void schedule(TimerTask task, long delay, long period) {
        if (delay < 0)
            throw new IllegalArgumentException("Negative delay.");
        if (period <= 0)
            throw new IllegalArgumentException("Non-positive period.");
        sched(task, System.currentTimeMillis() + delay, -period);
    }

    public void schedule(TimerTask task, Date firstTime, long period) {
        if (period <= 0)
            throw new IllegalArgumentException("Non-positive period.");
        sched(task, firstTime.getTime(), -period);
    }

    public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
        if (delay < 0)
            throw new IllegalArgumentException("Negative delay.");
        if (period <= 0)
            throw new IllegalArgumentException("Non-positive period.");
        sched(task, System.currentTimeMillis() + delay, period);
    }

    public void scheduleAtFixedRate(TimerTask task, Date firstTime,
                                    long period) {
        if (period <= 0)
            throw new IllegalArgumentException("Non-positive period.");
        sched(task, firstTime.getTime(), period);
    }

    /**
     * 添加任务,原子操作
     *
     * @param task
     * @param time
     * @param period
     */
    private void sched(TimerTask task, long time, long period) {
        if (time < 0) throw new IllegalArgumentException("Illegal execution time.");
        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();
        }
    }

    /**
     * queue所有任务置为null.
     */
    public void cancel() {
        synchronized (queue) {
            thread.newTasksMayBeScheduled = false;
            queue.clear();
            queue.notify();  // In case queue was already empty.
        }
    }

    /**
     * 将所有状态为CANCELLED的任务从queue中移除
     *
     * @return
     */
    public int purge() {
        int result = 0;
        synchronized (queue) {
            for (int i = queue.size(); i > 0; i--) {
                if (queue.get(i).state == TimerTask.CANCELLED) {
                    queue.quickRemove(i);
                    result++;
                }
            }
            if (result != 0) queue.heapify();
        }
        return result;
    }
}
// 用于封装一个任务
public abstract class TimerTask implements Runnable {

    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);
        }
    }
}

164540_UBbr_3342652.jpg

// 用于存储任务
public class TaskQueue {
    /**
     * 以数组的形式,维护的是一个平衡二叉树
     */
    private TimerTask[] queue = new TimerTask[128];
    private int size = 0;   // 没有 queue[0] ,应该是为了方便记忆

    int size() {
        return size;
    }

    void add(TimerTask task) {
        if (size + 1 == queue.length) {
            queue = Arrays.copyOf(queue, 2 * queue.length);  // 扩充为原来的一倍
        }
        queue[++size] = task;
        fixUp(size);
    }

    TimerTask getMin() {
        return queue[1];
    }

    TimerTask get(int i) {
        return queue[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() {
        return size == 0;
    }

    void clear() {
        for (int i = 1; i <= size; i++) queue[i] = null;
        size = 0;
    }

    // 向上寻找比自己小
    private void 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;
        }
    }

    // 向下寻找比自己大
    private void fixDown(int k) {
        int j;
        while ((j = k << 1) <= size && j > 0) {
            if (j < size && queue[j].nextExecutionTime > queue[j + 1].nextExecutionTime) j++; 
            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);
    }
}
// 用于执行未执行任务
public class TimerThread extends Thread {

    boolean newTasksMayBeScheduled = true;

    private TaskQueue queue;

    TimerThread(TaskQueue queue) {
        this.queue = queue;
    }

    public void run() {
        try {
            mainLoop();
        } finally {
            synchronized (queue) {
                newTasksMayBeScheduled = false;
                queue.clear();
            }
        }
    }

    // 核心代码
    private void mainLoop() {
        while (true) {
            try {
                TimerTask task;
                boolean taskFired;
                synchronized (queue) {
                    /**
                     * 线程启动后并未执行,等待queue.notify(),以免做无用功
                     */
                    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) {
                                // 已经执行过了,至少时间过了
                                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) {
            }
        }
    }
}

cancle与purge区别

/**
 * 清空任务队列
 */
public void cancel() {
    synchronized(queue) {
        thread.newTasksMayBeScheduled = false;
        queue.clear();
        queue.notify();  // In case queue was already empty.
    }
}
/**
 * 将所有标志位CANCELLED状态的任务移除掉
 */
public int purge() {
    int result = 0;

    synchronized(queue) {
        for (int i = queue.size(); i > 0; i--) {
            if (queue.get(i).state == TimerTask.CANCELLED) {
                queue.quickRemove(i);
                result++;
            }
        }

        if (result != 0)
            queue.heapify();
    }

    return result;
}

转载于:https://my.oschina.net/u/3342652/blog/1486418

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值