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

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

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

    E81086713E446D36F62B2AA2A3502B5EB155

    Java雜家

    雜七雜八。。。一家之言

    BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
      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值。
    現(xiàn)在我們來改變這個正常情況:
    1)保持程序運行
    2)通過系統(tǒng)時間欄把系統(tǒng)時間往前調(diào)一天。

    過一會兒,你會發(fā)現(xiàn)該程序停止輸出了?

    對,要看到下一個輸出,你得等一天了,在這種情況下,你即使現(xiàn)在重新調(diào)整到正確系統(tǒng)時間,你仍然得等到下一天才能看到輸出。

    為什么呢?
    下面是JDK中Timer調(diào)度的核心代碼(在原有注釋的基礎(chǔ)上加了一些):
    ?/**
    ?????*?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)?{
    ????????????}
    ????????}
    ????}
    那么,我們?nèi)绾文茏孴imer調(diào)度不依賴這種系統(tǒng)時間呢?
    Windows API中GetTickCount()返回系統(tǒng)自啟動以來的毫秒數(shù)。我們可以用這個來替代System.currentTimeMillis().這樣即使改變系統(tǒng)時間
    Timer的調(diào)度也不會所影響。

    改完后再來測試一把
    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));
    ????????
    ????}

    }

    這時的輸出沒有再受系統(tǒng)時間的改變了。

    本文代碼下載:
    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 就必須每個操作系統(tǒng)都提供系統(tǒng)啟動時鐘的功能, 但是你的這個就會引入另一個 Bug, 如果系統(tǒng)重啟, 然后啟動時鐘就會被重置(我們假設(shè)應(yīng)用存儲狀態(tài)后繼續(xù)執(zhí)行), 依賴這種做法的定時器也會失效. 所以我覺得 Sun 沒有按照這種想法來 Fix 第一是不是所有系統(tǒng)都提供系統(tǒng)啟動時間(典型的嵌入式設(shè)備)的API, 第二是這種做法又會引入新的問題. 一般來說依賴當前時間做定時是個比較簡單實用的思路, Windows 軟件防止過期后繼續(xù)使用也是在注冊表里記錄第一次使用的時間, 以后如果發(fā)現(xiàn)時間超前就會判定為超出試用期.

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

    發(fā)現(xiàn)剛發(fā)的評論不小心改掉了, 我說的是服務(wù)器在生產(chǎn)環(huán)境下不中斷應(yīng)用這么大的時間改動很危險, 不現(xiàn)實.  回復  更多評論
      

    # 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èi)執(zhí)行N次,而實際上少執(zhí)行了幾次,這是不可接受的。

    在Linux下,GetTickCount()可以用times()函數(shù)來實現(xiàn)。
    #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)就不會有這個問題. 它是調(diào)用系統(tǒng)原生的timer功能,Windows下SetTimer()函數(shù), gtk下用gtk_timeout_add()函數(shù).   回復  更多評論
      


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


    網(wǎng)站導航:
     
    主站蜘蛛池模板: 久久精品电影免费动漫| 国产成人免费a在线资源| 国产亚洲日韩在线a不卡| 久久久久无码精品亚洲日韩| 日韩一区二区免费视频| 久久精品国产免费观看| 9久热这里只有精品免费| 午夜亚洲国产精品福利| 亚洲a级在线观看| 亚洲综合一区二区精品导航| 亚洲人成精品久久久久| 亚洲?V无码成人精品区日韩| 在线免费观看视频你懂的| 18勿入网站免费永久| 91福利视频免费观看| 日本视频免费高清一本18| 亚洲精品国产自在久久 | 国产精品无码免费视频二三区| 免费看男女下面日出水来| 嫩草影院在线播放www免费观看| 免费毛片毛片网址| 久久精品国产亚洲AV天海翼| 亚洲剧情在线观看| 亚洲精品国产手机| 中文字幕亚洲精品| 亚洲最新视频在线观看| 亚洲午夜未满十八勿入| 亚洲AV永久纯肉无码精品动漫| 亚洲最大激情中文字幕| 亚洲另类激情综合偷自拍图| 精品国产香蕉伊思人在线在线亚洲一区二区| 四虎永久成人免费| 免费v片视频在线观看视频| 国产一级理论免费版| 免费v片视频在线观看视频| yy6080久久亚洲精品| 亚洲?V无码乱码国产精品| 亚洲高清无码综合性爱视频| 亚洲午夜国产精品无卡| 亚洲最大黄色网址| 亚洲国产高清美女在线观看 |