java线程之Timer实现原理解析


1. 整体图解

整体结构图解

2. 包含任务执行逻辑的 TimerTask 抽象类

  • 任务抽象类 TimerTask 的生命周期表示如下:
TimerTask的生命周期
  • 任务抽象类 TimerTask 的属性详细解释如下:
TimerTask类的属性解析
  • 任务抽象类 TimerTask 的实例方法:
TimerTask类的实例方法

3. 任务队列 TaskQueue

TaskQueue 内部采用最小堆来实现优先队列, 其各种操作的复杂度不超过O(logn)

  • TaskQueue 类的属性
TaskQueue类的属性
  • TaskQueue 类的实例方法
    TaskQueue类的实例方法

    TaskQueue类的实例方法

    TaskQueue类的实例方法

    辅助方法来维持最小堆的性质

4. 执行任务的线程类 TimerThread

执行任务的线程类 TimerThread 继承 Thread 类, 用来执行任务队列中的任务, 因此, Timer 类调度的所有任务都是在单线程中按执行时间先后顺序执行的

  • TimerThread 类的属性

    TimerThread类的属性

  • TimerThread 类的实例方法

    run方法

mainloop 方法详细解释如下:

private void mainLoop() {
        while (true) {
            try {
                TimerTask task;
                boolean taskFired;
                synchronized (queue) {
                    // 任务队列为空, 让当前执行线程放弃queue锁
                    while (queue.isEmpty() && newTasksMayBeScheduled) {
                        queue.wait();
                    }
                    // 执行期间发现任务队列为空, 即没有任务需要执行, 因此跳出循环
                    if (queue.isEmpty()) {
                        break;
                    }
                    long currentTime, executionTime;
                    task = queue.getMin();
                    synchronized (task.lock) {
                        if (task.state == TimerTask.TimerTaskStatus.CANCELLED) {
                            queue.removeMin();
                            continue; // 开始下一次循环去执行下一个任务
                        }
                        currentTime = System.currentTimeMillis();
                        executionTime = task.nextExecutionTime;
                        if (taskFired = (executionTime <= currentTime)) { // 任务的开始时间早于当前时间, 则立即执行
                            if (task.period == 0) { // 非周期型任务
                                queue.removeMin();
                                task.state = TimerTask.TimerTaskStatus.EXECUTED;
                            } else { // 周期型任务
                                // schedule 与 scheduleAtFixedRate 的区别体现在这里
                                // 当执行时间早于当前时间时, schedule系列方法执行时没有追赶性, scheduleAtFixedRate系列方法执行时具有追赶性
                                queue.rescheduleMin(task.period < 0 ? currentTime - task.period : executionTime + task.period);
                            }
                        }
                    }
                    if (!taskFired) { // 还未到时间执行任务
                        queue.wait(executionTime - currentTime);
                    }
                }
                if (taskFired) { // 可以执行任务(注意: 没有锁)
                    task.run();
                }
            } catch (InterruptedException e) {
            }
        }
    }

5. Timer 类解析

  • Timer 类的属性
Timer类的属性
  • Timer 类的构造方法
Timer类的构造方法
  • Timer 类的 cancel() 方法
cancel方法
  • schedule 系列方法
schedule系列方法
  • scheduleAtFixedRate 系列方法
scheduleAtFixedRate系列方法

schedulescheduleAtFixedRate 方法的具体执行逻辑放在 sched 方法上:

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;
        }
        // 将任务task的属性设置好并存放在任务队列queue上
        synchronized (queue) {
            if (!thread.newTasksMayBeScheduled) {
                throw new IllegalArgumentException("Timer already cancelled.");
            }
            synchronized (task.lock) {
                if (task.state != TimerTask.TimerTaskStatus.VIRGIN) {
                    throw new IllegalArgumentException("Task already scheduled or cancelled!");
                }
                task.nextExecutionTime = time;
                task.period = period;
                task.state = TimerTask.TimerTaskStatus.SCHEDULED;
            }
            queue.add(task);
            // 若加入任务前队列为空则要通知执行任务的线程, 使其从WAITING状态切换为RUNNABLE状态
            if (queue.getMin() == task) {
                queue.notify(); 
            }
        }
   }

注意: schedulescheduleAtFixedRate 方法的区别在于当执行时间早于当前时间时, schedule 方法不具有追赶性, 而 scheduleAtFixedRate 方法具有追赶性;

你可能感兴趣的:(java线程之Timer实现原理解析)