(java并发)ScheduledThreadPoolExcutor

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());  
        }  
    }  
}
相关文章
相关标签/搜索