amp@java

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            99 隨筆 :: 0 文章 :: 228 評(píng)論 :: 0 Trackbacks
          做GUI程序的時(shí)候,通常有個(gè)后臺(tái)工作線程在努力工作,但是中間又需要一些暫停,而關(guān)閉程序的時(shí)候,必須立即結(jié)束那個(gè)線程,退出程序,也有的時(shí)候需要停止后臺(tái)線程,但不關(guān)閉程序。例如,做一個(gè)目錄監(jiān)控程序,發(fā)現(xiàn)目錄中有文件的時(shí)候,執(zhí)行一定的操作,執(zhí)行完之后沒(méi)有文件了,就要暫停一下,過(guò)幾秒或幾分鐘再次檢測(cè),這時(shí)候就要對(duì)線程進(jìn)行暫停操作,如果在暫停的時(shí)候,用戶要關(guān)閉程序,就必須馬上停止線程,如果用戶需要暫停檢測(cè),按下某個(gè)按鈕后,需要讓線程馬上停止,但再次按下某個(gè)按鈕,線程又必須馬上開(kāi)始。

          以前我都是通過(guò)檢測(cè)停止標(biāo)記和用Thread.sleep(time)來(lái)完成的,后臺(tái)線程的每次循環(huán)都要檢查停止標(biāo)記,如果發(fā)現(xiàn)停止標(biāo)記已設(shè)定,就不再循環(huán),退出線程,在線程內(nèi)部,如果需要暫停,就執(zhí)行Thread.sleep(time)。通過(guò)把線程的setDaemon(true)方法,還可以讓線程作為后臺(tái)線程,當(dāng)圖形界面關(guān)閉后,線程也自動(dòng)退出。

          但是,這種方式有個(gè)問(wèn)題,如果我需要在圖形界面上點(diǎn)擊按鈕來(lái)停止線程,但并不退出程序,而點(diǎn)擊按鈕的時(shí)候線程正處于sleep狀態(tài),就對(duì)它沒(méi)有任何辦法,只能讓它醒過(guò)來(lái)再操作,如果sleep的時(shí)間比較長(zhǎng),例如1分鐘,那么點(diǎn)擊按鈕之后,用戶最多要等1分鐘才能把線程停下來(lái)。當(dāng)然,Thread對(duì)象有個(gè)interrupt方法,但是已經(jīng)被標(biāo)記為過(guò)期,一般不建議使用了。感謝評(píng)論中watchzerg的提醒,Thread的interrupt()并沒(méi)有標(biāo)記為過(guò)期,可以按照他的說(shuō)法來(lái)操作,更為簡(jiǎn)單。

          怎么讓線程能暫停,又能隨時(shí)叫醒呢?原來(lái)Java里最原始的對(duì)象Object就自帶此功能。

          每個(gè)Object都有wait(time)和notify()方法,前者就是讓擁有該Obejct的線程處于暫停狀態(tài),后者則讓線程馬上喚醒,通過(guò)這兩個(gè)方法,就能夠滿足上述的所有要求。

          首先,建立一個(gè)同步對(duì)象:
          Object syncObj = new Object();

          然后在線程中需要暫停的地方,調(diào)用該對(duì)象的wait(time)方法:
          synchronized (syncObj) {
                 syncObj.wait(60*1000);
          }

          在圖形界面的按鈕監(jiān)聽(tīng)事件中,對(duì)該對(duì)象執(zhí)行notify()方法:
                  button_1.addSelectionListener(new SelectionAdapter() {
                      @Override
                      public void widgetSelected(SelectionEvent e) {

                          thread.setStop(true);
                          synchronized (syncObj) {
                                  syncObj.notify();
                           }
                          //為了等待線程退出,還可以加上以下語(yǔ)句:
                          thread.join();

                      }
                  });

          posted on 2015-03-10 16:52 amp@java 閱讀(7691) 評(píng)論(2)  編輯  收藏 所屬分類: Java common

          評(píng)論

          # re: 如何讓線程暫停,又能隨時(shí)喚醒? 2015-03-31 10:26 watchzerg
          自己定制停止標(biāo)志位這種方法是有很多不妥的。《effective java》里也很早就說(shuō)過(guò)“當(dāng)線程在sleep時(shí),無(wú)法檢測(cè)停止標(biāo)志位”這種缺陷。作者的建議是在循環(huán)中使用“檢測(cè)Thread.currentThread().isInterrupted()”來(lái)代替“檢測(cè)自定義的停止標(biāo)志位”,需要終止該線程的時(shí)候直接調(diào)用該線程的interrupt()方法,這樣不管這個(gè)線程是sleep還是在檢測(cè)循環(huán),都可以幾乎立即優(yōu)雅的終止執(zhí)行。  回復(fù)  更多評(píng)論
            

          # re: 如何讓線程暫停,又能隨時(shí)喚醒? 2015-04-02 16:48 amp@java
          @watchzerg
          非常感謝,原來(lái)我記錯(cuò)了,我還以為interrupt()方法已經(jīng)被標(biāo)記為過(guò)期了。  回復(fù)  更多評(píng)論
            

          主站蜘蛛池模板: 含山县| 余干县| 博爱县| 开封县| 北川| 泗水县| 乌什县| 玉龙| 葫芦岛市| 宜阳县| 蓬莱市| 黑山县| 行唐县| 措勤县| 黎川县| 英吉沙县| 临城县| 云梦县| 景宁| 浠水县| 永靖县| 遂宁市| 乌审旗| 长垣县| 万源市| 长白| 葫芦岛市| 田林县| 富民县| 望都县| 上杭县| 化州市| 驻马店市| 永嘉县| 铅山县| 嵊州市| 梅州市| 大余县| 德清县| 河间市| 定边县|