1.用timer缺点很是大
java
Timer 的优势在于简单易用,但因为全部任务都是由同一个线程来调度,所以全部任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到以后的任务。多线程
咱们关于定时/周期操做都是经过Timer来实现的。可是Timer有如下几种危险
a. Timer是基于绝对时间的。容易受系统时钟的影响。
b. Timer只新建了一个线程来执行全部的TimeTask。全部TimeTask可能会相关影响
c. Timer不会捕获TimerTask的异常,只是简单地中止。这样势必会影响其余TimeTask的执行。 并发
2.ScheduledThreadPoolExecutor.net
鉴于 Timer 的上述缺陷,Java 5 推出了基于线程池设计的ScheduledThreadPoolExecutor。其设计思想是,每个被调度的任务都会由线程池中一个线程去执行,所以任务是并发执行的,相互之间不会受到干扰。需 要注意的是,只有当任务的执行时间到来时,ScheduedExecutor 才会真正启动一个线程,其他时间 ScheduledExecutor 都是在轮询任务的状态。线程
有如下四个调度器的方法:设计
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit); public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit); public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit); public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);
那么这四个方法有什么区别呢?其实第一个和第二个区别不大,一个是Runnable、一个是Callable,内部包装后是同样的效果;因此把头两个方法几乎当成一种调度,那么三种状况分别是:code
一、 进行一次延迟调度:延迟delay这么长时间,单位为:TimeUnit传入的的一个基本单位,例如:TimeUnit.SECONDS属于提供好的枚举信息;(适合于方法1和方法2)。排序
二、 屡次调度,每次依照上一次预计调度时间进行调度,例如:延迟2s开始,5s一次,那么就是二、七、十二、17,若是中间因为某种缘由致使线程不够用,没有获得调度机会,那么接下来计算的时间会优先计算进去,由于他的排序会被排在前面,有点相似Timer中的:scheduleAtFixedRate方法,只是这里是多线程的,它的方法名也叫:scheduleAtFixedRate,因此这个是比较好记忆的(适合方法3)get
三、 屡次调度,每次按照上一次实际执行的时间进行计算下一次时间,同上,若是在第7秒没有被获得调度,而是第9s才获得调度,那么计算下一次调度时间就不是12秒,而是9+5=14s,若是再次延迟,就会延迟一个周期以上,也就会出现少调用的状况(适合于方法3);it
四、 最后补充execute方法是一次调度,指望被当即调度,时间为空
public class ScheduledThreadPoolExecutorDemo { public static void main(String[] args) { ScheduledThreadPoolExecutor scheduledExecutor = new ScheduledThreadPoolExecutor(1); /** * new timeTaskForException() 要执行的任务线程 * 1000:延迟多长时间执行 * 2000: 每隔多少长时间执行一次 * TimeUnit.MILLISECONDS:时间单位 */ scheduledExecutor.scheduleAtFixedRate(new timeTaskForException(), 1000, 2000, TimeUnit.MILLISECONDS); scheduledExecutor.scheduleAtFixedRate(new timeTaskForPrintSYSTime(), 1000, 3000, TimeUnit.MILLISECONDS); } static class timeTaskForException implements Runnable{ public void run() { throw new RuntimeException(); } } static class timeTaskForPrintSYSTime implements Runnable { public void run() { System.out.println(System.nanoTime()); } } }