天天看点

Java并发编程:Timer和TimerTask

Timer是一个调度器,TimerTask是调度器中的任务。

例如:

Timer timer = new Timer();
timer.schedule(new TimerTask() {
        public void run() {
            System.out.println("abc");
        }
}, 20000 , 1000);
           

20s后开始执行,每秒执行一次。

1.常用方法

public

void

schedule(TimerTask task, 

long

delay);

调度一个task,经过delay(ms)后开始进行调度,仅仅调度一次

public

void

schedule(TimerTask task, Date time);

在指定的时间点time上调度一次。

---------------------------------------------------------------------------------------------------------------------------

public

void

schedule(TimerTask task, 

long

delay, 

long

period);

调度一个task,在delay(ms)后开始调度,每次调度完后,最少等待period(ms)后才开始调度。

public

void

schedule(TimerTask task, Date firstTime, 

long

period);

调度一个task,在指定时间点开始调度,每次调度完后,最少等待period(ms)后才开始调度。

---------------------------------------------------------------------------------------------------------------------------

public

void

scheduleAtFixedRate(TimerTask task, 

long

delay, 

long

period);

调度一个task,在delay(ms)后开始调度,然后每经过period(ms)再次调度。

public

void

scheduleAtFixedRate(TimerTask task, Date firstTime,

long

period);

调度一个task,在指定时间点开始调度,然后每经过period(ms)再次调度。

----------------------------------------------------------------------------------------------------------------------------

schedule和scheduleAtFixedRate区别,

schedule在计算下一次执行的时间的时候,是通过当前时间(在任务执行前得到) + 时间片,而scheduleAtFixedRate方法是通过现在应该执行的时间+ 时间片,前者是运行的实际时间,而后者是理论时间点。

构造方法:

构造方法1:无参构造方法,简单通过Tiemer为前缀构造一个线程名称:

public Timer() {
    this("Timer-" + serialNumber());
}
           

创建的线程不为主线程,主线程结束后,timer自动结束,而无需使用cancel来完成对timer的结束。

构造方法2:传入了是否为后台线程,后台线程当且仅当进程结束时,自动注销掉。

public Timer(boolean isDaemon) {
    this("Timer-" + serialNumber(), isDaemon);
}
           

2.调度机制

Timer和TimerTask的简单组合是多线程的嘛?不是,一个Timer内部包装了“一个Thread”和“一个Task”队列,这个队列按照一定的方式将任务排队处理,包含的线程在Timer的构造方法调用时被启动,这个Thread的run方法无限循环这个Task队列,若队列为空且没发生cancel操作,此时会一直等待,如果等待完成后,队列还是为空,则认为发生了cancel从而跳出死循环,结束任务;循环中如果发现任务需要执行的时间小于系统时间,那么根据任务的时间片重新计算下次执行时间,若时间片为0代表只执行一次,则直接移除队列即可。TimerTask的cancel方法是取消单个任务的执行,即将其状态置为CANCELLED,这样在调用Timer的purge方法时,会将任务队列中状态为CANCELLED的任务清除,并对最小堆进行重排序。任务队列是用最小堆实现的,具体是:用一个数组实现最小堆,下标从1开始。

多线程使用Executors.newScheduledThreadPool

继续阅读