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

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

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

    E81086713E446D36F62B2AA2A3502B5EB155

    Java雜家

    雜七雜八。。。一家之言

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      40 Posts :: 1 Stories :: 174 Comments :: 0 Trackbacks
    先看個小測試程序:
    package?test;

    import?java.util.Timer;
    import?java.util.TimerTask;

    public?class?TestTimer?extends?TimerTask{

    ????
    int?number;
    ????
    /**
    ?????*?
    @param?args
    ?????
    */
    ????
    public?static?void?main(String[]?args)?{
    ????????Timer?timer
    =new?Timer();
    ????????timer.schedule(
    new?TestTimer(), 1000, 1000);
    ????????
    ????}

    ????
    public?void?run()?{
    ???????System.out.println(
    "number="+(++number));
    ????????
    ????}

    }
    正常情況該程序每秒打印當前的 number值。
    現在我們來改變這個正常情況:
    1)保持程序運行
    2)通過系統時間欄把系統時間往前調一天。

    過一會兒,你會發現該程序停止輸出了?

    對,要看到下一個輸出,你得等一天了,在這種情況下,你即使現在重新調整到正確系統時間,你仍然得等到下一天才能看到輸出。

    為什么呢?
    下面是JDK中Timer調度的核心代碼(在原有注釋的基礎上加了一些):
    ?/**
    ?????*?The?main?timer?loop.??(See?class?comment.)
    ?????
    */
    ????
    private?void?mainLoop()?{
    ????????
    while?(true)?{
    ????????????
    try?{
    ????????????????
    //to?be?scheduled?task
    ????????????????TimerTask?task;
    ????????????????
    //fired?one?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

    ????????????????????
    //?Queue?nonempty;?look?at?first?evt?and?do?the?right?thing
    ????????????????????long?currentTime,?executionTime;
    ????????????????????task?
    =?queue.getMin();
    ????????????????????
    synchronized(task.lock)?{
    ????????????????????????
    if?(task.state?==?TimerTask.CANCELLED)?{
    ????????????????????????????
    //find?the?first?task?from?the?queue.
    ????????????????????????????queue.removeMin();
    ????????????????????????????
    continue;??//?No?action?required,?poll?queue?again
    ????????????????????????}
    ????????????????????????
    //here?,use?system?current?time?to?determin?whether?or?not?fire?a?task
    ????????????????????????currentTime?=?System.currentTimeMillis();
    ????????????????????????executionTime?
    =?task.nextExecutionTime;
    ????????????????????????
    //So?when?we?change?system?time?to?long?ago,this?expression?will?be?evaluate?to?false
    ????????????????????????if?(taskFired?=?(executionTime<=currentTime))?{
    ????????????????????????????
    if?(task.period?==?0)?{?//?Non-repeating,?remove
    ????????????????????????????????queue.removeMin();
    ????????????????????????????????task.state?
    =?TimerTask.EXECUTED;
    ????????????????????????????}?
    else?{?//?Repeating?task,?reschedule
    ????????????????????????????????queue.rescheduleMin(
    ??????????????????????????????????task.period
    <0???currentTime???-?task.period
    ????????????????????????????????????????????????:?executionTime?
    +?task.period);
    ????????????????????????????}
    ????????????????????????}
    ????????????????????}
    ????????????????????
    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調度不依賴這種系統時間呢?
    Windows API中GetTickCount()返回系統自啟動以來的毫秒數。我們可以用這個來替代System.currentTimeMillis().這樣即使改變系統時間
    Timer的調度也不會所影響。

    改完后再來測試一把
    public?class?TestTimer2?extends?com.yovn.labs.util.TimerTask{
    ????
    int?number;
    ????
    /**
    ?????*?
    @param?args
    ?????
    */
    ????
    public?static?void?main(String[]?args)?{
    ????????com.yovn.labs.util.Timer?timer
    =new?com.yovn.labs.util.Timer();
    ????????timer.schedule(
    new?TestTimer2(),?1000,?1000);
    ????????
    ????}

    ????
    public?void?run()?{
    ???????System.out.println(
    "number="+(++number));
    ????????
    ????}

    }

    這時的輸出沒有再受系統時間的改變了。

    本文代碼下載:
    source code

    posted on 2007-03-17 10:40 DoubleH 閱讀(2191) 評論(3)  編輯  收藏

    Feedback

    # re: Fix JDK Timer的bug(確認是個bug,見http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4290274) 2007-03-17 12:45 BeanSoft
    看了看那個 Bug 頁, 貌似 JDK 1.5 也沒 Fix. Submit Date 11-NOV-1999. 所以我覺得要 Fix 就必須每個操作系統都提供系統啟動時鐘的功能, 但是你的這個就會引入另一個 Bug, 如果系統重啟, 然后啟動時鐘就會被重置(我們假設應用存儲狀態后繼續執行), 依賴這種做法的定時器也會失效. 所以我覺得 Sun 沒有按照這種想法來 Fix 第一是不是所有系統都提供系統啟動時間(典型的嵌入式設備)的API, 第二是這種做法又會引入新的問題. 一般來說依賴當前時間做定時是個比較簡單實用的思路, Windows 軟件防止過期后繼續使用也是在注冊表里記錄第一次使用的時間, 以后如果發現時間超前就會判定為超出試用期.

    JDK 必須要為不同的平臺提供一致的特性, 所以這個 Bug 改起來還真是有點困難. 不過添加一個能獲取系統啟動時間的 API 倒是值得考慮(部分平臺可用).

    發現剛發的評論不小心改掉了, 我說的是服務器在生產環境下不中斷應用這么大的時間改動很危險, 不現實.  回復  更多評論
      

    # re: Fix JDK Timer的bug(確認是個bug,見http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4290274) 2007-03-17 13:04 Javacap
    @BeanSoft
    用戶可能誤操作,改完以后再改回來也是不行的。另外也不一定要這么大的時間改變。改一分鐘,就會導致延遲一分鐘。假如用戶使用scheduleAtFixRate,則本來期望一段時間內執行N次,而實際上少執行了幾次,這是不可接受的。

    在Linux下,GetTickCount()可以用times()函數來實現。
    #include <sys/times.h>

    long GetTickCount()
    {
    struct tms tm;
    return times(&tm);
    }

      回復  更多評論
      

    # re: Fix JDK Timer的bug(http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4290274) 2007-03-17 18:38 喜來樂哈哈
    選擇SWT的話,用Display.timerExec (int milliseconds, Runnable runnable)就不會有這個問題. 它是調用系統原生的timer功能,Windows下SetTimer()函數, gtk下用gtk_timeout_add()函數.   回復  更多評論
      


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 91免费国产在线观看| 女人与禽交视频免费看| 亚洲熟女乱综合一区二区| 亚洲日本一线产区和二线| 桃子视频在线观看高清免费完整| 亚洲爱情岛论坛永久| 亚洲精品第一国产综合野| 最近中文字幕完整免费视频ww| 无码专区—VA亚洲V天堂| 久久狠狠躁免费观看2020| 精品亚洲国产成AV人片传媒| 亚洲xxxxxx| 在线观看免费成人| 爱情岛亚洲论坛在线观看| 免费h成人黄漫画嘿咻破解版| 一级毛片高清免费播放| 亚洲中文字幕久久精品无码APP| 国产免费一区二区三区不卡 | 亚洲一卡2卡4卡5卡6卡残暴在线| 久久www免费人成看片| 亚洲youjizz| 亚洲VA综合VA国产产VA中| 国产视频精品免费视频| 免费观看美女裸体网站| 国产亚洲精品免费| 亚洲国产另类久久久精品黑人| 国产精品无码亚洲一区二区三区| 免费在线观看视频a| 波多野结衣免费一区视频| 亚洲老熟女@TubeumTV| 在线观看91精品国产不卡免费| 四虎一区二区成人免费影院网址| 在线视频免费观看www动漫| 日韩毛片一区视频免费| 国产精品免费视频播放器| 亚洲一区二区三区免费视频| 国产黄色片在线免费观看| 久久99久久成人免费播放| 亚洲国产精品日韩在线观看| 国产一级淫片a免费播放口之| 你懂的免费在线观看网站|