写完了基础篇,想了非常久要不要去写进阶篇。去写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 结束!");
}
}

JAVA随笔篇一(Timer源代码分析和scheduleAtFixedRate的使用)的更多相关文章

  1. Java中arraylist和linkedlist源代码分析与性能比較

    Java中arraylist和linkedlist源代码分析与性能比較 1,简单介绍 在java开发中比較经常使用的数据结构是arraylist和linkedlist,本文主要从源代码角度分析arra ...

  2. Java集合系列之TreeMap源代码分析

    一.概述 TreeMap是基于红黑树实现的.因为TreeMap实现了java.util.sortMap接口,集合中的映射关系是具有一定顺序的,该映射依据其键的自然顺序进行排序或者依据创建映射时提供的C ...

  3. Android4.42-Setting源代码分析之蓝牙模块Bluetooth(下)

    接着上一篇Android4.42-Settings源代码分析之蓝牙模块Bluetooth(上) 继续蓝牙模块源代码的研究 THREE.蓝牙模块功能实现 switch的分析以及本机蓝牙重命名和可见性的分 ...

  4. Android4.42-Settings源代码分析之蓝牙模块Bluetooth(上)

    继上一篇Android系统源代码剖析(一)---Settings 接着来介绍一下设置中某个模块的源代码.本文依然是基于Android4.42源代码进行分析,分析一下蓝牙模块的实现.建议大致看一下关于S ...

  5. java同步包种ArrayBlockingQueue类的分析与理解

    前言: ArrayBlockingQueue类是一个堵塞队列.重要用于多线程操作的条件. 一,官方解释 一个建立在数组之上被BlockingQueue绑定的堵塞队列.这个队列元素顺序是先进先出.队列的 ...

  6. Spark SQL 源代码分析系列

    从决定写Spark SQL文章的源代码分析,到现在一个月的时间,一个又一个几乎相同的结束很快,在这里也做了一个综合指数,方便阅读,下面是读取顺序 :) 第一章 Spark SQL源代码分析之核心流程 ...

  7. Java提高篇——通过分析 JDK 源代码研究 Hash 存储机制

    HashMap 和 HashSet 是 Java Collection Framework 的两个重要成员,其中 HashMap 是 Map 接口的常用实现类,HashSet 是 Set 接口的常用实 ...

  8. Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6642463 在前面几篇文章中,我们详细介绍了A ...

  9. Monkey源代码分析番外篇之Android注入事件的三种方法比較

    原文:http://www.pocketmagic.net/2012/04/injecting-events-programatically-on-android/#.VEoIoIuUcaV 往下分析 ...

随机推荐

  1. linux tar命令 压缩、打包、解压 详解

    linux tar命令 压缩.打包.解压 详解 1.常用压缩命令 tar –czvf 压缩后的文件.tar.gz 要压缩的文件 2.常用解压命令 tar –xzvf 解压后的文件.tar.gz [要解 ...

  2. oracle 归档模式开启后数据库宕机解决过程

    首先按照网友说的shutdown immediately,结果hang了半个小时也么反应. 然后检查日志,全盘搜索.trc,发现 (D:\app\oracle\diag\rdbms\cms1u\cms ...

  3. JAVA爬虫代码

    工程目录: 所需要的jar包为:   jsoup-1.10.2.jar /** * Created by wangzheng on 2017/2/19. */ public class Article ...

  4. '@P0'附近有语法错误

    做一个分页查询功能,使用到了TOP #{pagenum}然后就报错了.'@P0'附近有语法错误 未解决:#{pagenum}改成${pagenum},但是mybatis报参数未找到错误, 解决:将对应 ...

  5. GPIO复位功能说明

    根据STM32L0x3参考手册RM0367,每个General-Purpose IO口,有以下寄存器: 1.4个32位的控制寄存器,分别为GPIOx_MODER,GPIOx_OTYPER,GPIOx_ ...

  6. java环境变量和tomcat环境变量配置

    一.JAVA环境变量的配置1.首先下载JDK JDK可以在Oracle(甲骨文)公司的官方网站http://www.oracle.com下载2.安装完成后查看JDK安装路径一般是C:\Program ...

  7. 【转】使用PowerDesigner的建模创建升级管理数据库

    使用PowerDesigner的建模创建升级管理数据库 PowerDesigner是一种著名的CASE建摸工具,最开始为数据库建模设计,即物理模型(Physical Data Model)用于生成数据 ...

  8. 转载:一位资深程序员大牛给予Java初学者的学习路线建议

    一位资深程序员大牛给予Java初学者的学习路线建议   java学习这一部分其实也算是今天的重点,这一部分用来回答很多群里的朋友所问过的问题,那就是我你是如何学习Java的,能不能给点建议?今天我是打 ...

  9. 深入学习JS执行--创建执行上下文(变量对象,作用域链,this)

    一.介绍 本篇继上一篇深入理解js执行--单线程的JS,这次我们来深入了解js执行过程中的执行上下文. 本篇涉及到的名词:预执行,执行上下文,变量对象,活动对象,作用域链,this等 二.预执行 在上 ...

  10. JavaWeb面试(七)

    61,JDBC访问数据库的基本步骤是什么?1,加载驱动2,通过DriverManager对象获取连接对象Connection3,通过连接对象获取会话4,通过会话进行数据的增删改查,封装对象5,关闭资源 ...