<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 閱讀(2185) 評論(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()函數.   回復  更多評論
      


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


    網站導航:
     
    主站蜘蛛池模板: 国产亚洲午夜高清国产拍精品 | 亚洲伊人成无码综合网 | 亚洲国产精品无码久久久| 日韩av无码免费播放| 国产亚洲成人在线播放va| 一级毛片免费在线观看网站| 免费午夜爽爽爽WWW视频十八禁 | 一级毛片无遮挡免费全部| 国产免费午夜a无码v视频| 美女露100%胸无遮挡免费观看| 国产又黄又爽又刺激的免费网址| 精品国产亚洲AV麻豆| 亚洲 小说区 图片区 都市| 一级毛片a女人刺激视频免费| 亚洲国产精品13p| 一级a性色生活片久久无少妇一级婬片免费放 | 五级黄18以上免费看| 又大又粗又爽a级毛片免费看| 亚洲七久久之综合七久久| 美女被免费喷白浆视频| 亚洲午夜电影在线观看| 114一级毛片免费| 亚洲午夜一区二区三区| 30岁的女人韩剧免费观看| 亚洲高清中文字幕| 可以免费看黄视频的网站| 国产午夜亚洲精品国产| 精品久久久久久久免费人妻| 在线观看亚洲电影| 亚洲中文字幕无码爆乳av中文| 国产精品福利在线观看免费不卡| 亚洲精品国产高清嫩草影院 | 亚洲看片无码在线视频| 日韩高清在线免费看| 羞羞漫画在线成人漫画阅读免费| 亚洲一区二区三区无码影院| 永久在线观看免费视频 | 亚洲爽爽一区二区三区| 国产在线观看免费av站| 亚洲第一页在线视频| 成人免费毛片观看|