Timer & TimerTask 深入分析
来源:互联网 发布:广联达软件怎么用 编辑:程序博客网 时间:2024/06/05 07:36
在java中,有一个常用的定时机制,Timer&TimerTask。你可以方便地:
1)在某个时刻做某件事情, public void schedule(TimerTask task, Date when);
2)在一段延迟后做某件事情,public void schedule(TimerTask task, long delay);
在这两种方式中,都可以指定做这件事情的频率,用以下两个方法:public void schedule(TimerTask task, long delay, long period);public void schedule(TimerTask task, Date when, long period);
废话少说,还是看个例子吧:
import java.io.IOException;import java.util.Timer;public class TimerTest { public static void main(String[] args) { Timer timer = new Timer(); timer.schedule(new MyTask(), 1000, 2000); //在1秒后执行此任务,每次间隔2秒,如果传递一个Data参数,就是在某个固定的时间执行这个任务. while(true) { try { int ch = System.in.read(); if(ch-'c'==0) { timer.cancel(); //结束任务 } } catch (IOException e) { e.printStackTrace(); } }}static class MyTask extends java.util.TimerTask { // 这是你的任务线程 @Override public void run() { // accomplish your task here }}
可以说,Timer 提供了一个异步任务的启动机制。说到异步,呵呵,肯定就有多线程啦。这里涉及到了2个或者说是3个线程:
1)当前线程,也就是TimerTest 中 Main 方法跑的那个线程,这个不需要多说,都懂的。
2)任务线程,也就是MyTask 线程。这个也不复杂,看看TimerTask的实现就知道了:
public abstract class TimerTask implements Runnable { *** *** public abstract void run();}
问题是这个任务是单独开了一个线程吗?不急,后面有解答。
3)Timer 线程;
Timer 本身还单独开了一个线程吗?是的!看看Timer 的代码就明白了。策略模式。Timer 将具体的功能实现委托给静态内部类TimerImpl。Timer 类中有一个 静态内部类 TimerImpl,而它又继承了Thread,让我们接着来分析下这个TimerImple 子线程的生命周期:
创建:当Timer 实例构造的时候,子线程被启动;那么它什么时候结束的呢?实际上就是看看TimerImpl.run() 方法中的while(true) 循环是怎么退出的。
a) 当Timer.cancel() 被调用时,cancelled 标志被置为true,循环退出,线程结束;
b)当某个task的run() 方法异常退出时,cancelled 也会被置为 true,循环退出,线程结束。
try { task.run(); taskCompletedNormally = true; } finally { if (!taskCompletedNormally) { synchronized (this) { cancelled = true; } } }
以上代码还揭示了一个容易被忽视的真相,看看task.run(); 你是不是明白了什么,原来 TimerTask 虽然实现了Runnable 接口,但TimerTask并没有被start,而是被直接运行run() 方法。所以,TimerTask并没有单独开一个线程,而是就跑在TimerImpl 子线程中的。基于这样的事实,你不能在你的TimeTask的run() 方法中做过于耗时的操作,否则可能影响到其他task的按时执行。
呵呵,也许你会奇怪了,Runnable 不就是为多线程机制准备的吗?嗯,Runnable 主要是为多线程机制准备的,但不尽然,看看它的定义和注释吧:
/** * Represents a command that can be executed. Often used to run code in a * different {@link Thread}. */public interface Runnable { /** * Starts executing the active part of the class' code. This method is * called when a thread is started that has been created with a class which * implements {@code Runnable}. */ public void run();}
看见最上面的那行注释了吧,通常(often)运行在另外一个线程中,但并非总是(always)。所以,这个run未必总是跑在另外一个线程中的。其实,Runnable的这种看似另类的用法,也是比较常用的。
c)当TimerTask 队列为空,且TimerImple.finished 标志被置为true。而这个标志什么时候被置为true的呢,这个问题很有意思。看看Timer的另外一个静态内部类:
private static final class FinalizerHelper { private final TimerImpl impl; FinalizerHelper(TimerImpl impl) { this.impl = impl; } @Override protected void finalize() throws Throwable { try { synchronized (impl) { impl.finished = true; impl.notify(); } } finally { super.finalize(); } } }
当 FinalizerHelper 的实例,也就是Timer的一个私有成员变量(finalizer)被GC时,FinalizerHelper.finalize() 方法被JVM调用到,TimerImple.finished 标志被置为true。可以看到,Timer.finalizer 并没有被引用到,所以它应该是最早被GC掉的,这确保了它能完成一个光荣使命 ~~~~~~~ 帮助杀死TimerImpl 线程。
Timer 对Task 的管理
在TimerImple 对 Task 的具体管理操作又委托给了它自己的一个内部类 TimerHeap。在TimerHeap 内部定义了一个可动态扩展的TimerTask数组,这个数组实现了一个任务队列,越早执行的任务,排在越前面。
- Timer & TimerTask 深入分析
- 定时器之Timer和TimerTask深入分析
- Timer 和TimerTask分析
- Java Timer&TimerTask原理分析
- Java Timer&TimerTask源码分析
- 《Java源码分析》:Timer/TimerTask
- Java多线程总结(3)— Timer 和 TimerTask深入分析
- Timer TimerTask
- timer ,timertask
- timer timertask
- timer,timerTask
- Java Timer 源码深入分析
- Timer和TimerTask详解
- Timer与TimerTask入门
- Timer和TimerTask 示例
- Timer,TimerTask简单讲解
- Timer,Timertask的使用
- Timer和TimerTask详解
- WPF对Excel文件的导入导出
- vim插件之pathogen,NERDTree,Command-T,Powerline
- opendpi 源码分析(二)
- Restart your Cocoa application using Sparkle
- 项目4-奇数因子
- Timer & TimerTask 深入分析
- 怎样在Linux中查看apache是用那个httpd.conf
- 批量设置flash文档中TextField 使用设备字体
- C++中的智能指针(Smart Pointer)
- vs 最常用的快捷键 背吧背吧背吧背吧背吧背吧
- 算法研究之快速排序
- dictionary字典
- Linux系统下的C语言开发都需要学些什么
- WPF编程宝典:使用C_#.2008和.NET.3.5(第2版)(奋斗的小鸟)_PDF 电子书