JAVA随笔篇一(Timer源代码分析和scheduleAtFixedRate的使用)
写完了基础篇,想了非常久要不要去写进阶篇。去写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的使用)的更多相关文章
- Java中arraylist和linkedlist源代码分析与性能比較
Java中arraylist和linkedlist源代码分析与性能比較 1,简单介绍 在java开发中比較经常使用的数据结构是arraylist和linkedlist,本文主要从源代码角度分析arra ...
- Java集合系列之TreeMap源代码分析
一.概述 TreeMap是基于红黑树实现的.因为TreeMap实现了java.util.sortMap接口,集合中的映射关系是具有一定顺序的,该映射依据其键的自然顺序进行排序或者依据创建映射时提供的C ...
- Android4.42-Setting源代码分析之蓝牙模块Bluetooth(下)
接着上一篇Android4.42-Settings源代码分析之蓝牙模块Bluetooth(上) 继续蓝牙模块源代码的研究 THREE.蓝牙模块功能实现 switch的分析以及本机蓝牙重命名和可见性的分 ...
- Android4.42-Settings源代码分析之蓝牙模块Bluetooth(上)
继上一篇Android系统源代码剖析(一)---Settings 接着来介绍一下设置中某个模块的源代码.本文依然是基于Android4.42源代码进行分析,分析一下蓝牙模块的实现.建议大致看一下关于S ...
- java同步包种ArrayBlockingQueue类的分析与理解
前言: ArrayBlockingQueue类是一个堵塞队列.重要用于多线程操作的条件. 一,官方解释 一个建立在数组之上被BlockingQueue绑定的堵塞队列.这个队列元素顺序是先进先出.队列的 ...
- Spark SQL 源代码分析系列
从决定写Spark SQL文章的源代码分析,到现在一个月的时间,一个又一个几乎相同的结束很快,在这里也做了一个综合指数,方便阅读,下面是读取顺序 :) 第一章 Spark SQL源代码分析之核心流程 ...
- Java提高篇——通过分析 JDK 源代码研究 Hash 存储机制
HashMap 和 HashSet 是 Java Collection Framework 的两个重要成员,其中 HashMap 是 Map 接口的常用实现类,HashSet 是 Set 接口的常用实 ...
- Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6642463 在前面几篇文章中,我们详细介绍了A ...
- Monkey源代码分析番外篇之Android注入事件的三种方法比較
原文:http://www.pocketmagic.net/2012/04/injecting-events-programatically-on-android/#.VEoIoIuUcaV 往下分析 ...
随机推荐
- linux tar命令 压缩、打包、解压 详解
linux tar命令 压缩.打包.解压 详解 1.常用压缩命令 tar –czvf 压缩后的文件.tar.gz 要压缩的文件 2.常用解压命令 tar –xzvf 解压后的文件.tar.gz [要解 ...
- oracle 归档模式开启后数据库宕机解决过程
首先按照网友说的shutdown immediately,结果hang了半个小时也么反应. 然后检查日志,全盘搜索.trc,发现 (D:\app\oracle\diag\rdbms\cms1u\cms ...
- JAVA爬虫代码
工程目录: 所需要的jar包为: jsoup-1.10.2.jar /** * Created by wangzheng on 2017/2/19. */ public class Article ...
- '@P0'附近有语法错误
做一个分页查询功能,使用到了TOP #{pagenum}然后就报错了.'@P0'附近有语法错误 未解决:#{pagenum}改成${pagenum},但是mybatis报参数未找到错误, 解决:将对应 ...
- GPIO复位功能说明
根据STM32L0x3参考手册RM0367,每个General-Purpose IO口,有以下寄存器: 1.4个32位的控制寄存器,分别为GPIOx_MODER,GPIOx_OTYPER,GPIOx_ ...
- java环境变量和tomcat环境变量配置
一.JAVA环境变量的配置1.首先下载JDK JDK可以在Oracle(甲骨文)公司的官方网站http://www.oracle.com下载2.安装完成后查看JDK安装路径一般是C:\Program ...
- 【转】使用PowerDesigner的建模创建升级管理数据库
使用PowerDesigner的建模创建升级管理数据库 PowerDesigner是一种著名的CASE建摸工具,最开始为数据库建模设计,即物理模型(Physical Data Model)用于生成数据 ...
- 转载:一位资深程序员大牛给予Java初学者的学习路线建议
一位资深程序员大牛给予Java初学者的学习路线建议 java学习这一部分其实也算是今天的重点,这一部分用来回答很多群里的朋友所问过的问题,那就是我你是如何学习Java的,能不能给点建议?今天我是打 ...
- 深入学习JS执行--创建执行上下文(变量对象,作用域链,this)
一.介绍 本篇继上一篇深入理解js执行--单线程的JS,这次我们来深入了解js执行过程中的执行上下文. 本篇涉及到的名词:预执行,执行上下文,变量对象,活动对象,作用域链,this等 二.预执行 在上 ...
- JavaWeb面试(七)
61,JDBC访问数据库的基本步骤是什么?1,加载驱动2,通过DriverManager对象获取连接对象Connection3,通过连接对象获取会话4,通过会话进行数据的增删改查,封装对象5,关闭资源 ...