FORTUNE

          THE WAY TO THE MASTER...
          posts - 49, comments - 18, trackbacks - 0, articles - 1
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          SWT的線程間通信

          Posted on 2006-04-10 17:29 fortune 閱讀(1562) 評(píng)論(1)  編輯  收藏 所屬分類: java技術(shù)

          ?

          在SWT中,通常需要開(kāi)多個(gè)線程來(lái)執(zhí)行任務(wù),因?yàn)橹骶€程為UI線程,不能用太長(zhǎng)的時(shí)間來(lái)執(zhí)行某個(gè)任務(wù),否則會(huì)造成失去響應(yīng)的假象。
          SWT的線程通信有幾個(gè)要注意的地方:
          1、工作線程訪問(wèn)UI線程。不能在非UI線程中直接訪問(wèn)UI控件的值,要獲得或設(shè)置控件的值必須通過(guò)Display對(duì)象的asyncExec()或syncExec()函數(shù),一般的使用方法是:

          //代碼A:
          ?
          Display?disp??
          = ??Display.getDefault();
          ?
          if ?(disp? != ? null ?)??{
          ???disp.asyncExec(
          ????
          new ??Runnable()??{
          ????
          public ?? void ??run()??{
          ???????
          // ?在這里設(shè)置或獲得控件的值?
          ?}?
          }?
          );?
          }?

          2、內(nèi)部類與外部類的交流。內(nèi)部類調(diào)用外部類局部變量時(shí),該變量必須是final的,這樣在取得控件的值后返回給外部類處理時(shí)就比較麻煩。例如,在上面的代碼段中,有個(gè)匿名內(nèi)部類實(shí)現(xiàn)了Runnable接口,在里面的run()函數(shù)里可以訪問(wèn)到UI對(duì)象,但是,得到了對(duì)象的值怎么告訴外面的代碼呢?假如用普通的局部變量傳遞進(jìn)去,由于是final的,是不能賦值的,所以需要有一個(gè)封裝類來(lái)把需要返回的變量封裝起來(lái),這個(gè)封裝類是final的,但里面的成員變量是可變的,這樣就把內(nèi)部類里得到的東西傳遞到了外部,不過(guò)似乎比較麻煩,不知道有沒(méi)有更好的辦法。
          //代碼B:

          class
          ?StringWrapper?{
          ???public?String?uiValue;
          }
          StringWrapper?sw?
          =?new?StringWrapper();?
          Display?disp??
          =??Display.getDefault();
          ?
          if?(disp?!=?null?)??{
          ???disp.asyncExec(
          ????
          new??Runnable()??{
          ????
          public??void??run()??{
          ????????sw.uiValue?
          =?text.getText();//假設(shè)text是一個(gè)文本框?qū)ο?br />???????//?在這里設(shè)置或獲得控件的值?
          ????}?
          ???}?
          ???);?
          }?
          //這里就可以對(duì)sw.uiValue的值進(jìn)行訪問(wèn)
          3、線程間的同步。在上面的代碼B中,通過(guò)asyncExec()函數(shù)來(lái)取得控件的值所需要的時(shí)間比較長(zhǎng),如果在后面馬上訪問(wèn)那些值是得不到的,于是就需要有個(gè)同步的問(wèn)題,即在控件值取得之前先不進(jìn)行下一步操作。可以通過(guò)synchronized塊及wait(),notify()機(jī)制來(lái)實(shí)現(xiàn)同步。

          //代碼C:

          class?StringWrapper?{
          ???
          public?String?uiValue;
          }
          StringWrapper?sw?
          =?new?StringWrapper();?
          Display?disp??
          =??Display.getDefault();
          ?
          if?(disp?!=?null?)??{
          ???disp.asyncExec(
          ????
          new??Runnable()??{
          ????
          public??void??run()??{
          ????????
          synchronized(sw){
          ??????????sw.uiValue?
          =?text.getText();//假設(shè)text是一個(gè)文本框?qū)ο?/span>
          ????????????sw.notify();
          ?????????}
          ???????
          //?在這里設(shè)置或獲得控件的值
          ?
          ????}?
          ???}?
          ???);?
          }
          synchronized(sw){
          ??sw.wait();
          }?
          //這里就可以對(duì)sw.uiValue的值進(jìn)行訪問(wèn)

          但是這里會(huì)帶來(lái)一個(gè)問(wèn)題,假如很快就能取得控件的值,但后面還有很長(zhǎng)一段時(shí)間才會(huì)用到該值,如果把sw.wait()語(yǔ)句放在比較后的地方,就有可能造成死鎖,因?yàn)閟w已經(jīng)被notify之后才開(kāi)始wait的,再?zèng)]有其他線程來(lái)notify它了,它就只能一直wait下去……。為了解決這個(gè)問(wèn)題,可以(1)把sw.wait()緊跟在disp.asyncExec()后面;(2)給wait()設(shè)置一個(gè)timeout參數(shù),到了一定的時(shí)間還沒(méi)有東西notify它,它就自己超時(shí)。但這兩種辦法似乎都比較牽強(qiáng),沒(méi)有十足的保證,JDK文檔里面有個(gè)例子,是用while來(lái)判斷是否已經(jīng)達(dá)到了要求,如果已經(jīng)達(dá)到了就不再wait。
          //代碼D:

          class?StringWrapper?{
          ???
          public?String?uiValue;
          ???
          public?boolean?isValueSet;//是否已經(jīng)取得了控件的值
          }
          StringWrapper?sw?
          =?new?StringWrapper();?
          sw.isValueSet?
          =?false;
          Display?disp??
          =??Display.getDefault();
          ?
          if?(disp?!=?null?)??{
          ???disp.asyncExec(
          ????
          new??Runnable()??{
          ????
          public??void??run()??{
          ????????
          synchronized(sw){
          ??????????sw.uiValue?
          =?text.getText();//假設(shè)text是一個(gè)文本框?qū)ο?/span>
          ????????????sw.isValueSet?=?true;
          ????????????sw.notify();
          ?????????}
          ???????//?在這里設(shè)置或獲得控件的值

          ?
          ????}?
          ???}?
          ???);?
          }
          synchronized(sw){
          ??
          while(!sw.isValueSet){
          ????
          try{
          ??????sw.wait();
          ????}
          catch?(InterruptedException?e){
          ????}
          ??}
          }?
          //這里就可以對(duì)sw.uiValue的值進(jìn)行訪問(wèn)

          評(píng)論

          # re: SWT的線程間通信  回復(fù)  更多評(píng)論   

          2009-08-14 16:43 by 聯(lián)盟醫(yī)師
          好是好,但是感覺(jué)復(fù)雜化了
          主站蜘蛛池模板: 漯河市| 武宁县| 南木林县| 汝南县| 集贤县| 永川市| 青田县| 苍溪县| 洪洞县| 仙居县| 民权县| 三台县| 布尔津县| 兴化市| 十堰市| 湟中县| 兴和县| 汝州市| 鄯善县| 海晏县| 秀山| 巴林左旗| 株洲市| 六盘水市| 班戈县| 顺昌县| 门源| 乐安县| 平武县| 当雄县| 宁津县| 师宗县| 平安县| 上虞市| 武平县| 驻马店市| 沂南县| 肥西县| 绍兴县| 长海县| 大连市|