写完了基础篇,想了非常久要不要去写进阶篇。去写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. 六:Dubbo与Zookeeper、SpringMvc整合和使用

    DUBBO与ZOOKEEPER.SPRINGMVC整合和使用 互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,Dubbo是一个分布式服务框架 ...

  2. 利用Pycharm本地调试spark-streaming(包含kafka和zookeeper等操作)

    环境准备就不说了! 第一步:打开Pycharm,在File->Setting->Project Structure中点击Add Content Root 添加本地python调用java和 ...

  3. asp.net web api 文件上传

    1正确的做法 public class AvaterController : BaseApiController { [HttpPost] public async Task<IHttpActi ...

  4. [转载] 应用于负载均衡的一致性哈希及java实现

    转载自http://blog.csdn.net/haitao111313/article/details/7537799 这几天看了几遍一致性哈希的文章,但是都没有比较完整的实现,因此试着实现了一下, ...

  5. http2.4简单配置

    前言: 上一篇博文说到了http的发展以及http完整请求响应的工作流程. 一.开篇: 从最简单的静态服务器开始. 之前说过,http是应用层协议,必定会在用户空间体现出具体的应用程序.常见的http ...

  6. 对java泛型的理解

    正确的应用java泛型的特性可以更好的实现编程的开闭原则(对扩展开放,对修改关闭),这得益于java泛型提供的在程序运行时获取对象声明类型的特性. 静态语言的特性是在程序编译前进行声明,这样程序在编译 ...

  7. VueJS引入css或者less文件的一些坑

    我们在做Vue+webpack的时,难免会引入各种公共css样式文件,那么我们改如何引入呢?引入时会有那些坑呢? 首先,引入公共样式时,我们在“main.js”里使用AMD的方式引入,即 requir ...

  8. HTML5开发必备的工具

    现在除了移动APP开发之外,比较火的就是html5开发了,现阶段的HTML5被看做是Web开发者创建流行web应用的利器,增加了对视频和Canvas2D的支持,它的优点就是可以跨平台使用,比如你是开发 ...

  9. 这一次带你彻底了解Cookie

    前言 网络早期最大的问题之一是如何管理状态.简而言之,服务器无法知道两个请求是否来自同一个浏览器.当时最简单的方法是在请求时,在页面中插入一些参数,并在下一个请求中传回参数.这需要使用包含参数的隐藏的 ...

  10. JavaWeb框架_Struts2_(七)----->文件的上传和下载

    这个章节是Struts2框架应用最广泛的三个版块(上传下载.国际化.校验输入)之一,所以这一版块的学习还蛮重要的. 1. 章节目录 Struts2文件上传 单文件上传 拦截器实现文件过滤 文件上传常量 ...