<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    xylz,imxylz

    關(guān)注后端架構(gòu)、中間件、分布式和并發(fā)編程

       :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      111 隨筆 :: 10 文章 :: 2680 評論 :: 0 Trackbacks
    [本文地址:http://www.tkk7.com/Files/xylz/Inside.Java.Concurrency_32.ThreadPool.part5_ScheduledExecutorService.pdf]

    周期性任務(wù)調(diào)度前世

    在JDK 5.0之前,java.util.Timer/TimerTask是唯一的內(nèi)置任務(wù)調(diào)度方法,而且在很長一段時(shí)間里很熱衷于使用這種方式進(jìn)行周期性任務(wù)調(diào)度。

    首先研究下Timer/TimerTask的特性(至于javax.swing.Timer就不再研究了)。

    public void schedule(TimerTask task, long delay, long period) {
       
    if (delay < 0)
           
    throw new IllegalArgumentException("Negative delay.");
       
    if (period <= 0)
           
    throw new IllegalArgumentException("Non-positive period.");
        sched(task, System.currentTimeMillis()
    +delay, -period);
    }
    public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
       
    if (delay < 0)
           
    throw new IllegalArgumentException("Negative delay.");
       
    if (period <= 0)
           
    throw new IllegalArgumentException("Non-positive period.");
        sched(task, System.currentTimeMillis()
    +delay, period);
    }

     

    public class Timer {

       
    private TaskQueue queue = new TaskQueue();
       
    /**
         * The timer thread.
        
    */
       
    private TimerThread thread = new TimerThread(queue);
     

     

    java.util.TimerThread.mainLoop()

    private void mainLoop() {
       
    while (true) {
           
    try {
                TimerTask task;
               
    boolean taskFired;
               
    synchronized(queue) {
                   
    // Wait for queue to become non-empty
                    while (queue.isEmpty() && newTasksMayBeScheduled)
                        queue.wait();
                   
    if (queue.isEmpty())
                       
    break; // Queue is empty and will forever remain; die
    。。。。。。
                    
                   
    if (!taskFired) // Task hasn't yet fired; wait
                        queue.wait(executionTime - currentTime);
                }
               
    if (taskFired)  // Task fired; run it, holding no locks
                    task.run();
            }
    catch(InterruptedException e) {
            }
        }
    }

     

    上面三段代碼反映了Timer/TimerTask的以下特性:

    • Timer對任務(wù)的調(diào)度是基于絕對時(shí)間的。
    • 所有的TimerTask只有一個(gè)線程TimerThread來執(zhí)行,因此同一時(shí)刻只有一個(gè)TimerTask在執(zhí)行。
    • 任何一個(gè)TimerTask的執(zhí)行異常都會導(dǎo)致Timer終止所有任務(wù)。
    • 由于基于絕對時(shí)間并且是單線程執(zhí)行,因此在多個(gè)任務(wù)調(diào)度時(shí),長時(shí)間執(zhí)行的任務(wù)被執(zhí)行后有可能導(dǎo)致短時(shí)間任務(wù)快速在短時(shí)間內(nèi)被執(zhí)行多次或者干脆丟棄多個(gè)任務(wù)。

    由于Timer/TimerTask有這些特點(diǎn)(缺陷),因此這就導(dǎo)致了需要一個(gè)更加完善的任務(wù)調(diào)度框架來解決這些問題。

    周期性任務(wù)調(diào)度今生

    java.util.concurrent.ScheduledExecutorService的出現(xiàn)正好彌補(bǔ)了Timer/TimerTask的缺陷。

    public interface ScheduledExecutorService extends ExecutorService {
       
    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);
    }

     

    首先ScheduledExecutorService基于ExecutorService,是一個(gè)完整的線程池調(diào)度。另外在提供線程池的基礎(chǔ)上增加了四個(gè)調(diào)度任務(wù)的API。

    • schedule(Runnable command,long delay, TimeUnit unit):在指定的延遲時(shí)間一次性啟動任務(wù)(Runnable),沒有返回值。
    • schedule(Callable<V> callable, long delay, TimeUnit unit):在指定的延遲時(shí)間一次性啟動任務(wù)(Callable),攜帶一個(gè)結(jié)果。
    • scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit):建并執(zhí)行一個(gè)在給定初始延遲后首次啟用的定期操作,后續(xù)操作具有給定的周期;也就是將在 initialDelay 后開始執(zhí)行,然后在 initialDelay+period 后執(zhí)行,接著在 initialDelay + 2 * period 后執(zhí)行,依此類推。如果任務(wù)的任何一個(gè)執(zhí)行遇到異常,則后續(xù)執(zhí)行都會被取消。否則,只能通過執(zhí)行程序的取消或終止方法來終止該任務(wù)。如果此任務(wù)的任何一個(gè)執(zhí)行要花費(fèi)比其周期更長的時(shí)間,則將推遲后續(xù)執(zhí)行,但不會同時(shí)執(zhí)行。
    • scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit):創(chuàng)建并執(zhí)行一個(gè)在給定初始延遲后首次啟用的定期操作,隨后,在每一次執(zhí)行終止和下一次執(zhí)行開始之間都存在給定的延遲。如果任務(wù)的任一執(zhí)行遇到異常,就會取消后續(xù)執(zhí)行。否則,只能通過執(zhí)行程序的取消或終止方法來終止該任務(wù)。

    上述API解決了以下幾個(gè)問題:

    • ScheduledExecutorService任務(wù)調(diào)度是基于相對時(shí)間,不管是一次性任務(wù)還是周期性任務(wù)都是相對于任務(wù)加入線程池(任務(wù)隊(duì)列)的時(shí)間偏移。
    • 基于線程池的ScheduledExecutorService允許多個(gè)線程同時(shí)執(zhí)行任務(wù),這在添加多種不同調(diào)度類型的任務(wù)是非常有用的。
    • 同樣基于線程池的ScheduledExecutorService在其中一個(gè)任務(wù)發(fā)生異常時(shí)會退出執(zhí)行線程,但同時(shí)會有新的線程補(bǔ)充進(jìn)來進(jìn)行執(zhí)行。
    • ScheduledExecutorService可以做到不丟失任務(wù)。

    下面的例子演示了一個(gè)任務(wù)周期性調(diào)度的例子。

    package xylz.study.concurrency.executor;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;

    public class ScheduledExecutorServiceDemo {
       
    public static void main(String[] args) throws Exception{
            ScheduledExecutorService execService
    =   Executors.newScheduledThreadPool(3);
            execService.scheduleAtFixedRate(
    new Runnable() {
               
    public void run() {
                    System.out.println(Thread.currentThread().getName()
    +" -> "+System.currentTimeMillis());
                   
    try {
                        Thread.sleep(
    2000L);
                    }
    catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            },
    1, 1, TimeUnit.SECONDS);
           
    //
            execService.scheduleWithFixedDelay(new Runnable() {
               
    public void run() {
                    System.out.println(Thread.currentThread().getName()
    +" -> "+System.currentTimeMillis());
                   
    try {
                        Thread.sleep(
    2000L);
                    }
    catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            },
    1, 1, TimeUnit.SECONDS);
            Thread.sleep(
    5000L);
            execService.shutdown();
        }
    }

     

    一次可能的輸出如下:

    pool-1-thread-1 -> 1294672392657
    pool
    -1-thread-2 -> 1294672392659
    pool
    -1-thread-1 -> 1294672394657
    pool
    -1-thread-2 -> 1294672395659
    pool
    -1-thread-1 -> 1294672396657

     

    在這個(gè)例子中啟動了默認(rèn)三個(gè)線程的線程池,調(diào)度兩個(gè)周期性任務(wù)。第一個(gè)任務(wù)是每隔1秒執(zhí)行一次,第二個(gè)任務(wù)是以固定1秒的間隔執(zhí)行,這兩個(gè)任務(wù)每次執(zhí)行的時(shí)間都是2秒。上面的輸出有以下幾點(diǎn)結(jié)論:

    • 任務(wù)是在多線程中執(zhí)行的,同一個(gè)任務(wù)應(yīng)該是在同一個(gè)線程中執(zhí)行。
    • scheduleAtFixedRate是每次相隔相同的時(shí)間執(zhí)行任務(wù),如果任務(wù)的執(zhí)行時(shí)間比周期還長,那么下一個(gè)任務(wù)將立即執(zhí)行。例如這里每次執(zhí)行時(shí)間2秒,而周期時(shí)間只有1秒,那么每次任務(wù)開始執(zhí)行的間隔時(shí)間就是2秒。
    • scheduleWithFixedDelay描述是下一個(gè)任務(wù)的開始時(shí)間與上一個(gè)任務(wù)的結(jié)束時(shí)間間隔相同。流入這里每次執(zhí)行時(shí)間2秒,而周期時(shí)間是1秒,那么兩個(gè)任務(wù)開始執(zhí)行的間隔時(shí)間就是2+1=3秒。

    事實(shí)上ScheduledExecutorService的實(shí)現(xiàn)類ScheduledThreadPoolExecutor是繼承線程池類ThreadPoolExecutor的,因此它擁有線程池的全部特性。但是同時(shí)又是一種特殊的線程池,這個(gè)線程池的線程數(shù)大小不限,任務(wù)隊(duì)列是基于DelayQueue的無限任務(wù)隊(duì)列。具體的結(jié)構(gòu)和算法在以后的章節(jié)中分析。

    由于ScheduledExecutorService擁有Timer/TimerTask的全部特性,并且使用更簡單,支持并發(fā),而且更安全,因此沒有理由繼續(xù)使用Timer/TimerTask,完全可以全部替換。需要說明的一點(diǎn)事構(gòu)造ScheduledExecutorService線程池的核心線程池大小要根據(jù)任務(wù)數(shù)來定,否則可能導(dǎo)致資源的浪費(fèi)。

     

    [本文地址:http://www.tkk7.com/Files/xylz/Inside.Java.Concurrency_32.ThreadPool.part5_ScheduledExecutorService.pdf]


    ©2009-2014 IMXYLZ |求賢若渴
    posted on 2011-01-10 23:39 imxylz 閱讀(14461) 評論(32)  編輯  收藏 所屬分類: Java Concurrency

    評論

    # re: 深入淺出 Java Concurrency (32): 線程池 part 5 周期性任務(wù)調(diào)度 2011-01-11 12:06 打底褲
    果然深入淺出哈  回復(fù)  更多評論
      

    # re: 深入淺出 Java Concurrency (32): 線程池 part 5 周期性任務(wù)調(diào)度 2011-01-12 15:59 青菜貓
    樓主確實(shí)不錯(cuò),。有機(jī)會來杭州一起給我們團(tuán)隊(duì)講下  回復(fù)  更多評論
      

    # re: 深入淺出 Java Concurrency (32): 線程池 part 5 周期性任務(wù)調(diào)度 2011-02-09 16:28 wells
    海,兄弟可以交流下  回復(fù)  更多評論
      

    # re: 深入淺出 Java Concurrency (32): 線程池 part 5 周期性任務(wù)調(diào)度 2011-02-09 16:30 wells
    我是淘寶技術(shù)人員,有幾個(gè)問題想跟你交流下,我的郵箱是qing.yinbo@gmail.com,通過郵件我們可以交流下,期待你的email  回復(fù)  更多評論
      

    # re: 深入淺出 Java Concurrency (32): 線程池 part 5 周期性任務(wù)調(diào)度 2013-11-08 12:34 高永飛
    同樣基于線程池的ScheduledExecutorService在其中一個(gè)任務(wù)發(fā)生異常時(shí)會退出執(zhí)行線程,但同時(shí)會有新的線程補(bǔ)充進(jìn)來進(jìn)行執(zhí)行

    這句話有問題,任務(wù)發(fā)生RuntimeException時(shí),執(zhí)行該任務(wù)的線程會終止,這句話沒有問題。但是不會有新的線程補(bǔ)充進(jìn)來執(zhí)行。因?yàn)閳?zhí)行任務(wù)的后臺線程是調(diào)用scheduleWithFixedDelay或scheduleWithFixedDelay時(shí)創(chuàng)建的,可以參考ScheduledThreadPoolExecutor.delayedExecute的prestartCoreThread()。

    也就是說,如果想讓任務(wù)發(fā)生異常時(shí)照樣按時(shí)執(zhí)行后續(xù)的任務(wù),需要在任務(wù)里catch住所有異常。

    舉個(gè)例子,
    ScheduledExecutorService exec = Executors.newScheduledThreadPool(2);
    exec.scheduleWithFixedDelay(new Runnable() 。。。

    ScheduledExecutorService不會因?yàn)樵O(shè)置了size是2,而會在任務(wù)發(fā)生異常時(shí),再啟動一個(gè)線程繼續(xù)執(zhí)行。

    技術(shù)性的文章建議博主寫代碼檢驗(yàn)每一句話,尤其是博主這種瀏覽量大的文章。
    不過真心贊一下,博主寫的這一系列文章很不錯(cuò)!

    如果我說的有問題,請及時(shí)指正 qq:554312685  回復(fù)  更多評論
      

    # John 2014-05-02 03:26 Smithd559
    Good writeup, I am normal visitor of ones blog, maintain up the excellent operate, and It's going to be a regular visitor for a lengthy time. kbceedeffdadcddg  回復(fù)  更多評論
      

    # Good info 2014-05-04 21:05 Pharmd383
    Very nice site!  回復(fù)  更多評論
      

    # cheap cialis online 2014-05-16 16:48 cialis
    Hello!
      回復(fù)  更多評論
      

    # cheap cialis 2014-05-16 16:49 cheap_cialis
    Hello!
      回復(fù)  更多評論
      

    # viagra sale 2014-05-17 05:07 viagra_sale
    Hello!
      回復(fù)  更多評論
      

    # cialis tadalafil cheapest online 2014-05-17 05:28 tadalafil
    Hello!
      回復(fù)  更多評論
      

    # cialis online 2014-05-20 15:19 cialis_online
    Hello!
      回復(fù)  更多評論
      

    # viagra price 2014-05-20 15:20 viagra_price
    Hello!
      回復(fù)  更多評論
      

    # cheap cialis 2014-07-14 18:44 cheap_cialis
    Hello!
      回復(fù)  更多評論
      

    # cheap viagra 2014-07-14 18:45 cheap_viagra
    Hello!
      回復(fù)  更多評論
      

    # http://canadianviagragen7a.com/ 2014-07-17 15:14 with
    Hello!
      回復(fù)  更多評論
      

    # http://viagra7withoutprescription.com/ 2014-07-17 18:09 discount
    Hello!
      回復(fù)  更多評論
      

    # http://cheapgeneric7viagra.com/ 2014-07-17 18:10 discount
    Hello!
      回復(fù)  更多評論
      

    # buy generic cialis 2014-07-17 23:53 generic
    Hello!
      回復(fù)  更多評論
      

    # cialis fast delivery 2015-04-29 19:50 fast
    Hello!
      回復(fù)  更多評論
      

    # viagra fast delivery 2015-04-29 19:50 fast
    Hello!
      回復(fù)  更多評論
      

    # John 2015-06-01 07:45 Smithc667
    Thanksamundo for the post.Really thank you! Awesome. edebdbceaekadffd  回復(fù)  更多評論
      

    # cialis side effects 2016-03-30 22:23 side
    Hello!
      回復(fù)  更多評論
      

    # cialis 2016-04-05 23:27 cialis
    Hello!
      回復(fù)  更多評論
      

    # dosage of viagra 2016-04-05 23:27 of
    Hello!
      回復(fù)  更多評論
      

    # cialis 2016-04-05 23:28 cialis
    Hello!
      回復(fù)  更多評論
      

    # viagra 2016-04-05 23:29 viagra
    Hello!
      回復(fù)  更多評論
      

    # cialis 2016-04-06 07:16 cialis
    Hello!
      回復(fù)  更多評論
      

    # dosage of viagra 2016-04-06 07:16 of
    Hello!
      回復(fù)  更多評論
      

    # order cialis 2016-04-06 07:17 order_cialis
    Hello!
      回復(fù)  更多評論
      

    # order viagra 2016-04-06 07:18 order_viagra
    Hello!
      回復(fù)  更多評論
      

    # re: 深入淺出 Java Concurrency (32): 線程池 part 5 周期性任務(wù)調(diào)度 2018-08-03 17:21 bboymars
    任務(wù)是在多線程中執(zhí)行的,同一個(gè)任務(wù)應(yīng)該是在同一個(gè)線程中執(zhí)行。
    這個(gè)結(jié)論在我機(jī)子上運(yùn)行不對,我運(yùn)行如下:
    pool-1-thread-1 -> 任務(wù)a -> 1533287852227
    pool-1-thread-2 -> 任務(wù)b -> 1533287852227
    pool-1-thread-2 -> 任務(wù)a -> 1533287854227
    pool-1-thread-1 -> 任務(wù)b -> 1533287855230
    pool-1-thread-2 -> 任務(wù)a -> 1533287856230
    pool-1-thread-2 -> 任務(wù)a -> 1533287858234
    pool-1-thread-1 -> 任務(wù)b -> 1533287858234
    pool-1-thread-3 -> 任務(wù)a -> 1533287860236
    pool-1-thread-2 -> 任務(wù)b -> 1533287861237
    pool-1-thread-3 -> 任務(wù)a -> 1533287862237
    pool-1-thread-2 -> 任務(wù)a -> 1533287864240
    pool-1-thread-1 -> 任務(wù)b -> 1533287864240
    pool-1-thread-2 -> 任務(wù)a -> 1533287866244  回復(fù)  更多評論
      


    ©2009-2014 IMXYLZ
    主站蜘蛛池模板: 国产精品偷伦视频免费观看了| 国产成人无码免费看视频软件| 日韩a级毛片免费视频| 亚洲日本中文字幕区| 日本在线观看免费高清| 野花高清在线电影观看免费视频 | 无码欧精品亚洲日韩一区夜夜嗨 | 最近2019中文字幕mv免费看| 亚洲av永久无码精品表情包| 无人视频免费观看免费视频| 啦啦啦中文在线观看电视剧免费版 | 亚洲国产片在线观看| 中文字幕无码日韩专区免费| 亚洲成aⅴ人片久青草影院| 亚洲日韩一区二区三区| 亚洲美女视频免费| 亚洲AV日韩精品久久久久久| 香蕉国产在线观看免费| 午夜成人免费视频| 亚洲无限乱码一二三四区| 久久久精品午夜免费不卡| 亚洲性日韩精品一区二区三区| 亚洲高清一区二区三区电影| 黄+色+性+人免费| 久久精品国产亚洲av影院| 好久久免费视频高清| 国产日产亚洲系列| 一本久久免费视频| 又黄又爽的视频免费看| 在线观看亚洲AV每日更新无码| 亚洲精品视频在线观看免费| 久久香蕉国产线看观看亚洲片| 中文字幕乱码系列免费| 久久亚洲国产成人影院网站 | 2017亚洲男人天堂一| 国产92成人精品视频免费| 亚洲黄色免费观看| 中文字幕视频免费| 18gay台湾男同亚洲男同| 亚洲一区免费观看| 内射少妇36P亚洲区|