原文鏈接: ScheduledExecutorService執(zhí)行周期性或定時(shí)任務(wù) http://ketqi.blog.51cto.com/1130608/687681
ScheduledExecutorService擴(kuò)展了ExecutorService接口,提供時(shí)間排程的功能。
| 方法名 | 含義 |
|---|---|
| schedule(Callable<V> callable, long delay, TimeUnit unit) | 創(chuàng)建并執(zhí)行在給定延遲后啟用的 ScheduledFuture。 |
| schedule(Runnable command, long delay, TimeUnit unit) | 創(chuàng)建并執(zhí)行在給定延遲后啟用的一次性操作。 |
| scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnitunit) | 創(chuàng)建并執(zhí)行一個(gè)在給定初始延遲后首次啟用的定期操作,后續(xù)操作具有給定的周期;也就是將在 initialDelay 后開始執(zhí)行,然后在initialDelay+period 后執(zhí)行,接著在 initialDelay + 2 * period 后執(zhí)行,依此類推。 |
| scheduleWithFixedDelay(Runnable command, long initialDelay, long delay,TimeUnit unit) | 創(chuàng)建并執(zhí)行一個(gè)在給定初始延遲后首次啟用的定期操作,隨后,在每一次執(zhí)行終止和下一次執(zhí)行開始之間都存在給定的延遲。 |
schedule方法被用來延遲指定時(shí)間來執(zhí)行某個(gè)指定任務(wù)。如果你需要周期性重復(fù)執(zhí)行定時(shí)任務(wù)可以使用scheduleAtFixedRate或者scheduleWithFixedDelay方法,它們不同的是前者以固定頻率執(zhí)行,后者以相對固定頻率執(zhí)行。
不管任務(wù)執(zhí)行耗時(shí)是否大于間隔時(shí)間,scheduleAtFixedRate和scheduleWithFixedDelay都不會導(dǎo)致同一個(gè)任務(wù)并發(fā)地被執(zhí)行。唯一不同的是scheduleWithFixedDelay是當(dāng)前一個(gè)任務(wù)結(jié)束的時(shí)刻,開始結(jié)算間隔時(shí)間,如0秒開始執(zhí)行第一次任務(wù),任務(wù)耗時(shí)5秒,任務(wù)間隔時(shí)間3秒,那么第二次任務(wù)執(zhí)行的時(shí)間是在第8秒開始。
ScheduledExecutorService的實(shí)現(xiàn)類,是ScheduledThreadPoolExecutor。ScheduledThreadPoolExecutor對象包含的線程數(shù)量是沒有可伸縮性的,只會有固定數(shù)量的線程。不過你可以通過其構(gòu)造函數(shù)來設(shè)定線程的優(yōu)先級,來降低定時(shí)任務(wù)線程的系統(tǒng)占用。
特別提示:通過
ScheduledExecutorService執(zhí)行的周期任務(wù),如果任務(wù)執(zhí)行過程中拋出了異常,那么過ScheduledExecutorService就會停止執(zhí)行任務(wù),且也不會再周期地執(zhí)行該任務(wù)了。所以你如果想保住任務(wù)都一直被周期執(zhí)行,那么catch一切可能的異常。
package test;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* create at 11-10-14
* @author KETQI
* @category
*/
public class TestScheduledThreadPoolExecutor {
private static SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) {
//ScheduledExecutorService exec=Executors.newScheduledThreadPool(1);
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
/**
*每隔一段時(shí)間打印系統(tǒng)時(shí)間,互不影響的<br/>
* 創(chuàng)建并執(zhí)行一個(gè)在給定初始延遲后首次啟用的定期操作,后續(xù)操作具有給定的周期;<br/>
* 也就是將在 initialDelay 后開始執(zhí)行,然后在initialDelay+period 后執(zhí)行,<br/>
* 接著在 initialDelay + 2 * period 后執(zhí)行,依此類推。
*/
exec.scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println(format.format(new Date()));
}
}, 1000, 5000, TimeUnit.MILLISECONDS);
//開始執(zhí)行后就觸發(fā)異常,next周期將不會運(yùn)行
exec.scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println("RuntimeException no catch,next time can't run");
throw new RuntimeException();
}
}, 1000, 5000, TimeUnit.MILLISECONDS);
//雖然拋出了運(yùn)行異常,當(dāng)被攔截了,next周期繼續(xù)運(yùn)行
exec.scheduleAtFixedRate(new Runnable() {
public void run() {
try{
throw new RuntimeException();
}catch (Exception e){
System.out.println("RuntimeException catched,can run next");
}
}
}, 1000, 5000, TimeUnit.MILLISECONDS);
/**
* 創(chuàng)建并執(zhí)行一個(gè)在給定初始延遲后首次啟用的定期操作,<br/>
* 隨后,在每一次執(zhí)行終止和下一次執(zhí)行開始之間都存在給定的延遲。
*/
exec.scheduleWithFixedDelay(new Runnable() {
public void run() {
System.out.println("scheduleWithFixedDelay:begin,"+format.format(new Date()));
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("scheduleWithFixedDelay:end,"+format.format(new Date()));
}
},1000,5000,TimeUnit.MILLISECONDS);
/**
* 創(chuàng)建并執(zhí)行在給定延遲后啟用的一次性操作。
*/
exec.schedule(new Runnable() {
public void run() {
System.out.println("The thread can only run once!");
}
},5000,TimeUnit.MILLISECONDS);
}
}