最近因为工作的需要,要用到Java的定时任务,JDK1.5之前的Timer和TimerTask类已经过时了,
特地从网上找了一些材料汇总了以下,方便以后的学习。
//删除其中一个任务
http://www.iteye.com/problems/78147
http://bbs.csdn.net/topics/380145101
http://olylakers.iteye.com/blog/1218243
http://www.2cto.com/kf/201208/145943.html
以下是原文转载,转载自:http://hi.baidu.com/yanfei_nn/item/c73802014089319b03ce1b5f
Java 一个优于Timer的定时器——ScheduledThreadPoolExecutor
1. TimeUnit 时间单元
换算进制:
|
1) 可以快速实现时间格式转换
toNanos、toMicros、toMillis、toSeconds、toMinutes、toHours、toDays
2) 以指定格式快速实现线程停滞
sleep
TimeUnit.SECONDS.sleep(1); <=> Thread.sleep(1000) // 线程等待1秒
2. ScheduledThreadPoolExecutor
1) ScheduledThreadPoolExecutor是在JDK1.5以后提供可以实现定时、重复运行任务的功能,类似Timer,优于Timer
2) 构造方法
a) ScheduledThreadPoolExecutor(int corePoolSize)使用给定核心池大小创建一个新 ScheduledThreadPoolExecutor
b)ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactorythreadFactory)使用给定的初始参数创建一个新对象
b可以提供线程创建工厂
|
3) 调度方法
a) schedule(Callable callable, long delay, TimeUnit unit); 延迟delay时间后开始执行callable
b) scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit); 延迟initialDelay时间后开始执行command,并且按照period时间周期性重复调用,如果command运行时间较长、可能会同时执行(周期时间包括command运行时间)
c) scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit); 延迟initialDelay时间后开始执行command,并且按照period时间周期性重复调用,并且保证在上次运行完后才会执行下一次(周期时间不包括command运行时间)
4) 全局线程方法参数
a) setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean value) 如果value为true,则在主线程shutdown()方法后如果还没有执行(未达到delay的时间),则延迟任务仍然有机会执行,反之则不会执行,直接退出。(针对b、c方法)
b) setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean value) 如果value为true,则在主线程shutdown()方法后如果还没有执行(未达到delay的时间),则延迟任务仍然有机会执行,反之则不会执行,直接退出。(针对a方法)
3. ScheduledFuture
在执行调度之后返回该对象。它可以判断任务是否已经执行、是否已经取消、取消以后的操作
4. 操作实例
|
以下转载的原文出处:http://www.360doc.com/content/12/0916/20/820209_236455178.shtml
-
Timer计时器有管理任务延迟执行("如1000ms后执行任务")以及周期性执行("如每500ms执行一次该任务")。但是,Timer存在一些缺陷,因此你应该考虑使用ScheduledThreadPoolExecu
tor作为代替品,Timer对调度的支持是基于绝对时间,而不是相对时间的,由此任务对系统时钟的改变是敏感的;ScheduledThreadExecutor只支持相对时间。 Timer的另一个问题在于,如果TimerTask抛出未检查的异常,Timer将会产生无法预料的行为。Timer线程并不捕获异常,所以TimerTask抛出的未检查的异常会终止timer线程。这种情况下,Timer也不会再重新恢复线程的执行了;它错误的认为整个Timer都被取消了。此时,已经被安排但尚未执行的TimerTask永远不会再执行了,新的任务也不能被调度了。 例子:
package com.concurrent.basic;
import java.util.Timer;
import java.util.TimerTask;public class TimerTest {
private Timer timer = new Timer(); // 启动计时器 public void lanuchTimer() { timer.schedule(new TimerTask() { public void run() { throw new RuntimeException(); } }, 1000 * 3, 500); } // 向计时器添加一个任务 public void addOneTask() { timer.schedule(new TimerTask() { public void run() { System.out.println("hello world"); } }, 1000 * 1, 1000 * 5); } public static void main(String[] args) throws Exception { TimerTest test = new TimerTest(); test.lanuchTimer(); Thread.sleep(1000 * 5);// 5秒钟之后添加一个新任务 test.addOneTask(); }
}
执行结果:
你可能希望第二个没有异常的线程会一直运行下去,然而实际情况如程序所示5秒钟后就中止了,还伴随着一个异常,异常的消息是"Timer already cancelled"。ScheduledThreadPoolExector妥善地处理了这个异常的任务,所以说在java5.0或更高的JDK中,几乎没有理由再使用Timer了。 java5.0后提供
-
public interface ScheduledExecutorService
- extends ExecutorService
-
一个 ExecutorService
,可安排在给定的延迟后运行或定期执行的命令。
schedule 方法使用各种延迟创建任务,并返回一个可用于取消或检查执行的任务对象。scheduleAtFixedRate 和 scheduleWithFixedDelay 方法创建并执行某些在取消前一直定期运行的任务。
而且不受时钟限制。
例子:
package com.concurrent.basic;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.TimeUnit;
public class ScheduledExecutorTest {