栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java中Timer定时器源码分析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java中Timer定时器源码分析

定时任务主要用到两个类,一个是Timer类,一个是TimerTask类。Timer类主要用于维护定时任务,管理任务的执行,TimerTask是具体执行任务的类。Timer类的schedule方法可以设置任务的运行时机,TimerTask抽象类中有run抽象方法,我们需要实际运行的任务代码就是放在这里。

Timer是一个类,用来管理java代码中需要依靠时间条件控制执行的方法,比如定时执行,定间隔时间执行等等。

Timer定时常用的有schedule方法和scheduleFixedRate方法:这两种方法非常相似,基本逻辑:

1. 接收到需要执行的任务task,首次执行时间time,时间间隔period;

2. 将time和period赋值给task的对应属性nextExecutionTime、period;

3. 将task任务加入queue队列

2. TimerTask类因为实现了Runable接口,即创建了线程,所以会在满足条件的时候就会执行线程。

Timer类

Timer类中定义的两个变量:任务队列和时间线程。

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

 

TaskQueue中定义了TimerTask[]类型的变量,初始长度是128.用于存放TimerTask;

TimerThread是继承了Thread的线程类,在这个类中有一个有参构造方法,用来获取TaskQueue类型的queue任务队列,里面的run方法就是要执行的方法:

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

    public void run() {
        try {
            mainLoop();
        } finally {
            // Someone killed this Thread, behave as if Timer cancelled
            synchronized(queue) {
                newTasksMayBeScheduled = false;
                queue.clear();  // Eliminate obsolete references
            }
        }
    }

run方法中的mainLoop方法是进行无限循环,检查是否满足条件,如果满足条件,就执行TimerTask实例的run方法。

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) {
        }
    }
}
schedule方法:
public void schedule(TimerTask task, Date firstTime, long period) {
        if (period <= 0)
            throw new IllegalArgumentException("Non-positive period.");
        sched(task, firstTime.getTime(), -period);
    }

 

在这个方法里将period改成负数传入sched方法。

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

 

参数:

  * TimerTask task,传入执行体,即满足时间条件就执行的方法,专门有一个抽象类Timetask来管理,需要重写Timetask抽象类里面的run方法进行执行。

  * Date firstTime,第一次执行时间,满足这个时间条件,就开始执行;

  * long period,执行间隔。

方法体:判断period是否小于等于0,如果小于等于0则抛出"Non-positive period."异常,反之正常则执行sched方法。firTime.getTime()是将Date类型转换为long类型如"1634039142877"、"1634039232120"....,getTime方法是将Date类型转换为long类型,常用于时间的比较时使用。

sched方法:
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();
        }
    }

 

参数: 参数还是和在scheduleAtFixedRate方法中基本一样,只不过Date转为long类型。

方法体:逻辑上就是把task加入到队列queue中。

add方法
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);
    }

其实task就是一个重写了run方法的TimerTask对象,执行重写后的run方法(Runable接口中的方法),

TimerTask类

状态:

static final int VIRGIN = 0;  //原始状态的

static final int SCHEDULED   = 1; //计划的,预定的

static final int EXECUTED    = 2; //已执行的

static final int CANCELLED   = 3; //已取消的

synchronized():同步代码块,将括号中的对象进行原子化执行

**TimerThread中的run和mainLoop方法**

public void run() {
    try {
        mainLoop();
    } finally {
        // Someone killed this Thread, behave as if Timer cancelled
        synchronized(queue) {
            newTasksMayBeScheduled = false;
            queue.clear();  // Eliminate obsolete references
        }
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/332477.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号