(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());  
        }  
    }  
}
相關文章
相關標籤/搜索