Java:轉(zhuǎn)載—— ScheduledExecutorService執(zhí)行周期性或定時(shí)任務(wù)

原文鏈接: 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);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容