亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

J2SE5.0用Executor靈活處理事件下發

2019-11-18 11:54:46
字體:
來源:轉載
供稿:網友

  每個java開發人員都熟悉異步事件下發的EventListener模式。許多人也寫過用來治理偵聽器和下發事件給其他組件的樣板代碼。偵聽器是簡單、通用、靈活和輕易實現的,但他涉及到其他開發人員寫的代碼,這可能引起問題:
  
  1、一個低效的偵聽器可能花費太長的時間來處理事件,這使得其他偵聽器等待并可能引起死鎖。
  
  2、在你派發事件給偵聽器器的時候,你可以控制下發的線程。但通常實現偵聽器的開發人員不能控制事件如何被下發到他們的代碼。
  
  3、在一個多媒體應用中,如何同步GUI事件(如動畫和用戶交互)和其他異步事件流(如語音、聲音和視頻)不那么清楚。
  
  這篇文章使用Doug Lea的Executor(現在是J2SE 5.0的一部分)使得事件派發更加靈活。你可以使用這種思想在以下方面:
  
  1、答應開發人員使用你的組件作為事件派發策略的插件,這樣就可以自定義事件的派發方式。
  
  2、使不同的偵聽器相互獨立,因此一個低效的偵聽器就不會影響其他的了。
  
  3、多元化來自不同異步資源的事件流。
  
  JAVA1.4兼容性注重:這篇文章使用J2SE 5.0的泛型來排除事件和偵聽器器的轉換。Dispatchable Event Library也包含一個非泛型的版本可以運行在JDK 1.4上。較早的JDK缺少內建的java.util.concurrent包,但你可以下載兼容的后續支持版本。
  
  標準偵聽器
  
  在本文示例中,會編寫一個使用ClipEven類也報告視頻片斷事件(如啟動和暫停等)和實現ClipListener接口響應事件的視頻編輯系統。
  
  import java.util.EventListener;
  class ClipEvent extends EventObject {
  //...}public interface ClipListener extends EventListener {
  public void clipUpdate(ClipEvent e);}
  
  在許多程序中,事件是由一些控制類來創建,他們不僅負責維護相應的偵聽器而且派發每一個事件給相應的偵聽器。通常,我們可以分離這職責并且將偵聽器的維護代理給一個簡單的助手類dispatcher。ClipEventDispatcher示例了這種事件派發的方式:
  
  import java.util.*;public class ClipEventDispatcher {
  final Collection listeners = new ArrayList();
  public synchronized void
  addListener(ClipListener l) {
  listeners.add(l);
  }
  public synchronized void
  removeListener(ClipListener l) {
  listeners.remove(l);
  }
  public void fireEvent(ClipEvent e) {
  for(Iterator i = copyListeners();
  i.hasNext();) {
  ClipListener l = (ClipListener) i.next();
  l.clipUpdate(e);
  }
  } PRivate synchronized Iterator copyListeners() {
  return new ArrayList(listeners).iterator();
  }
  }
  
  ClipEventDispatcher暴露出如前面所討論的典型的下發問題。假如任何一個ClipListener有較慢的clipUpdate方法實現就會導致其他偵聽器等待。派發器的作者決定哪一個線程調用fireEvent方法,而ClipListener的開發人員卻沒有辦法自定義事件的下發。
  
  JAVA中靈活的任務執行:Executor接口
  
  J2SE 5.0標準化了java.util.concurrent包,包含來自Doug Lea創建的Executor接口。Executor運行實現了java.lang.Runnable接口的任務。
  
  class MyCoolTask implements Runnable { public void run() {
  //... do useful stuff }}Thread t = new Thread(new MyCoolTask());t.start();
  
  在Executor使用Runnables是類似的:
  
  Executor e = ...e.execute(new MyCoolTask());
  
  轉遞給execute方法的Runnable任務包含被Executor調用的run方法。但不像Thread只可以調用啟動方法一次,Executors可以運行許多Runnable任務。不同的Executors體現不同的執行任務的策略。例如,J2SE 5.0提供一個Executor作為調度器,這意味著他可以按照配置的時間周期性地運行任務。在下一頁的Useful Executors部分具體描述了幾種不同的Executor,但首先我們來看一下如何用他們來解決事件派發問題。
  
  用DispatchableEvent增加靈活性
  
  為了使組合Executor和事件更輕易,我開發了一個Dispatchable Event Library,他提供了助手類DispatchableEventSupport(用來維護偵聽器和事件派發)。在內部,DispatchableEventSupport實例使用一個Executor來觸發事件,因此可以改變Executor來自定義事件下發策略。
  
  下面是一個使用DispatchableEvent類庫來重寫的ClipEventDispatcher示例:
  
  import org.recoil.pixel.dispatchable.*;import org.recoil.pixel.executor.*;public class ClipEventDispatcher {  Executor e = new DirectExecutor(); //[1] DispatchableEventSupport<ClipListener> d =
  new DispatchableEventSupport<ClipListener>(e);
  public void addListener(ClipListener l) {
  d.addListener(l);
  }
  public void removeListener(ClipListener l) {
  d.removeListener(l);
  }
  public void fireEvent(ClipEvent e) {
  d.fireEvent(new DispatchableEvent
  <ClipListener, ClipEvent>(e) {
  public void
  dispatch( ClipListener l, ClipEvent ce) {
  l.clipUpdate(ce); //[2]
  }
  });
  }}
  
  在行[1]上我們使用DirectExecutor來簡化重建原始的ClipEventDispatcher行為。事件下發可以通過變化使用的Executor來自定義,或者在DispatchableEventSupport被創建時或者在偵聽器增加時。
  
  在行[2]上你只需要如此簡單的代碼來集成到你的應用中。Dispatchable Event Library處理了事件下發的機制,通常你所需要做的只是調用的回調函數(如clipUpdate)
  
  Dispatchable Event Library詳解
  
  Dispatchable Event Library包含幾個有用的助手類來派發任何類型的事件。要害的幾個類在org.recoil.pixel.dispatchable包中:
  
  DispatchableEventDispatcher:使用Executor觸發事件,但不提供偵聽器的維護。在你想為現有的事件派發代碼增加靈活性是非常有用。
  
  DispatchableEventSupport:大部分應用想要使用這個助手類,他為DispatchableEventDispatcher增加了偵聽器維護。假如你了解java.beans.PropertyChangeSupport你會覺得他也很熟悉。
  
  PropertyChangeEventDispatcher:組合了DispatchableEventDispatcher
  
  和PropertyChangeSupport,為PropertyChangeEvents提供了靈活的派發策略。這也是一個研究如何將DispatchableEvents與現有代碼集成的好例子。
  
  DispatchableEvent:用來擴展你的事件下發代碼的抽象類。
  
  有用的Executors
  
  Dispatchable Event Library的力量來自可以被用來自定義事件下發的可用Executors。下面我來看一下可用的Executors組:
  
  Dispatchable Event Library包含org.recoil.pixel.executor包:
  
  DirectExecutor:DirectExecutor在同一線程內同步調用提供給他的代碼。假如和DispatchableEventSupport一起使用這個類,你可以得到通用的偵聽器行為,這也是一個有用的缺省值。
  
  AWTExecutor:AWTExecutor在AWT事件派發線程的調度代碼。事件與AWTEvents交互。因此,由這個Executor調用的偵聽器可以自由地調用更新AWT和Swing GUI組件的方法而不需要使用SwingUtilities.invokeLater(),因為他們已經在正確的線程中被子調用。
  
  MIDPExecutor:MIDPExecutor在J2ME MIDlet中與AWTExecutor一致。他確保你的事件通過需要與MIDlet's GUI交互的callSerially方法下發。
  
  例如,為了在AWT事件派發線程中使用AWTExecutor來下發ClipEvents:
  
  import org.recoil.pixel.dispatchable.*;
  import org.recoil.pixel.executors.*;
  Executor e = new AWTExecutor();DispatchableEventSupport<ClipListener> d =new
  DispatchableEventSupport<ClipListener>(e);
  
  J2SE5.0內建的Executor
  
  新的J2SE 5.0類java.util.concurrent.Executors被用來創建復雜的線程池。你可以在池中配置線程數量,設置延遲或者周期調度。
  
  例如,使用J2SE 5.0 Executor提供一個容納5個事件下發線程的線程池
  
  import org.recoil.pixel.dispatchable.*;
  import java.util.concurrent.*;
  Executor tp = Executors.newFixedThreadPool(5);
  DispatchableEventSupport<ClipListener> d = new
  DispatchableEventSupport<ClipListener>(tp);
  
  J2EE并沒有提供標準的線程池功能,但Executor可以通過JMS或者消息BEAN來實現提供可配置的事件下發。
  
  問題解決
  
  現在我們已經看到Dispatchable Event Library和一些Executors,我們可以看一上如何使用這些工具來避免常見的偵聽器問題。
  
  避免等待
  
  DispatchableEventSupport提供2個addListener方法來避免偵聽器等待問題:
  
  public void addListener(L listener); public void addListener(L listener,Executor executor);
  
  addListener(L listener)方法在DispatchableEventSupport被創建的時候共享默認的Executor集合。而addListener(L listener, Executor executor)方法關聯自定義的Executor。
  
  這種方式不僅為組件的使用者提供了自定義事件下發的一種好的方式,而且幫助他們通過只有2個參數的addListener方法來分離偵聽器。
  
  import org.recoil.pixel.dispatchable.*;public class SharedComponent {
  DispatchableEventSupport<ClipListener> d =
  new DispatchableEventSupport<ClipListener>();
  public void
  addListener(ClipListener l, Executor e) {
  d.addListener(l, e);
  }
  public void fireEvent(ClipEvent e) {
  d.fireEvent(new DispatchableEvent
  <ClipListener, ClipEvent>(e) {
  public void
  dispatch( ClipListener l, ClipEvent ce) {
  l.clipUpdate(ce);
  }
  });
  }
  [...]}
  
  給SharedComponent增加偵聽器的開發人員被強制為每一個偵聽器定義一個Executor。假設每一個開發人員保持Executor為私有的,那么他的偵聽器就有一定的分離量。這在他們使用基于線程池的Executor時非常有用。
  
  假如所有相關的代碼都在團隊的控制下,那么SharedComponent是足夠的,但這還不能完全解決等待問題。假如你因為使用遺留的或第三方代碼而必須支持低效的偵聽器時,你可以通過控制和強制每一個偵聽器擁有自己的Executor來增加相互的獨立性。
  
  import org.recoil.pixel.dispatchable.*;
  import java.util.concurrent.*;
  public class DefensiveComponent {
  private final
  DispatchableEventSupport<ClipListener> d =
  new DispatchableEventSupport<ClipListener>();
  public void addListener(ClipListener l) {
  Executor e=Executors.newSingleThreadExecutor();
  d.addListener(l, e);
  }
  public void removeListener(ClipListener l) {
  d.removeFirstInstanceOfListener(l);
  }
  public void fireEvent(ClipEvent e) {
  d.fireEvent(new DispatchableEvent
  <ClipListener, ClipEvent>(e) {
  public void
  dispatch( ClipListener l, ClipEvent ce) {
  l.clipUpdate(ce);
  }
  });
  }
  [...]}
  
  DefensiveComponent為每一個增加的偵聽器附加對應的事件下發線程,這就分離了低效的偵聽器并且確保偵聽器可以被獨立的處理;高效的偵聽器不需要等待低效的。這種策略是簡單而安全的,但也是高代價的,因為他必須創建和銷毀許多線程。在大部分情況下,需要通過Executors創建合理大小的線程池也平衡獨立性和代價。
  
  同步多事件流
  
  DispatchableEvent答應你通過一個簡單的Executor多元化相應事件來同步來自不同異步資源的事件。
  
  例如,考慮一個支持鼠標和語音識別的多模畫板應用。
  
  通常語音識別在一斷語音被識別時派發一個事件。想像用戶選擇一個圖形然后說“刪除”。顯然我們希望鼠標事件被首先處理,否則可能會刪除錯誤的對象。一種簡單地解決這個問題的方法是使用AWTExecutor來下發語音事件,他會在事件被收到時將其放在AWT事件隊列中,確保首先處理MouseEvents。
  
  這個想法可以擴展到更多的異步事件流,通過將每一個事件源作為引用放到一個共享的基于隊列的Executor中。每一個事件根據順序放在隊列中,交叉地下發。
  
  小結
  
  這篇文章專注于可能發生在偵聽器范例中的問題。我們看到一個簡單的派發類庫如何通過Executors被用來自定義事件下發。使用不同的策略你可以將你的組件與子系統(如AWT)集成,你可以通過答應客戶定義使用的Executor來給予他們更多的選擇,或者你可以從另一方面來分離低效的偵聽器來防止等待。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
97热在线精品视频在线观看| 欧美巨乳在线观看| 国产成人鲁鲁免费视频a| 亚洲国产日韩欧美综合久久| 久久精品免费播放| 成人中文字幕在线观看| 亚洲精品久久久久久下一站| 国产精品嫩草影院久久久| 欧美黑人一级爽快片淫片高清| 国产视频久久久| 国产成人精品优优av| 亚洲国内高清视频| 亚洲tv在线观看| 欧美性视频精品| 精品国产乱码久久久久酒店| 亚洲色图激情小说| 亚洲91av视频| 91精品视频大全| 欧美国产日韩视频| 中文字幕国产精品久久| 精品欧美一区二区三区| 欧美福利视频在线观看| 亚洲理论片在线观看| 97视频在线播放| 91在线高清视频| 亚洲精品黄网在线观看| 欧美成人激情图片网| 久久综合免费视频影院| 亚洲精品美女久久久久| 粉嫩老牛aⅴ一区二区三区| 91老司机精品视频| 亚洲精品美女久久久久| 国产精品久久久久久久app| 欧亚精品在线观看| 亚洲一区二区免费在线| 久久久久国产精品一区| 亚洲小视频在线观看| 欧美大片在线免费观看| 黄网站色欧美视频| 欧美成年人视频| 日韩美女av在线| 久久久精品国产一区二区| 欧美一级电影久久| 在线亚洲欧美视频| 国产精品高潮呻吟久久av无限| 免费成人高清视频| 亚洲伦理中文字幕| 日韩美女激情视频| 在线观看欧美日韩| 国产日韩欧美夫妻视频在线观看| 久久久久久一区二区三区| 国产精品偷伦视频免费观看国产| 亚洲美女www午夜| 国产精品69久久久久| 国产精品自拍视频| 日韩中文在线中文网三级| 91在线观看欧美日韩| 日韩精品免费视频| 国产欧美日韩视频| 欧美日本中文字幕| 中文字幕亚洲图片| 国产精品中文在线| 国产成人一区三区| 国内精品久久久久久| 成人午夜在线视频一区| 国产精品老女人精品视频| 欧美视频一二三| 亚洲色在线视频| 欧美中文字幕在线播放| 91精品免费久久久久久久久| 91精品视频免费观看| 欧美疯狂xxxx大交乱88av| 欧美另类99xxxxx| 国产午夜精品全部视频播放| 国外日韩电影在线观看| 2020国产精品视频| 亚洲欧美中文日韩v在线观看| 欧美理论电影在线观看| 91在线视频精品| 久久精品国产免费观看| 欧美黑人xxxⅹ高潮交| 精品久久香蕉国产线看观看gif| 97国产成人精品视频| 亚洲国产精品人人爽夜夜爽| 久久99青青精品免费观看| 538国产精品一区二区免费视频| 久久综合伊人77777蜜臀| 中日韩美女免费视频网址在线观看| 高清视频欧美一级| 国产精品久久久久久久久久小说| 亚洲在线一区二区| 欧美激情三级免费| 亚洲97在线观看| 日本成人黄色片| 午夜精品福利在线观看| 久久人人97超碰精品888| 国产97在线视频| 亚洲第一色中文字幕| 久久免费少妇高潮久久精品99| 国产日韩欧美影视| 国产精品中文久久久久久久| 欧美性生交xxxxx久久久| 亚洲综合日韩在线| 国产精品亚洲欧美导航| 97国产精品久久| 欧美成人黑人xx视频免费观看| 中文字幕亚洲激情| 欧美日韩亚洲91| 久久夜色撩人精品| 欧美美最猛性xxxxxx| 中文字幕欧美日韩| 欧美国产第二页| 欧美成人免费在线视频| 91精品久久久久久| 国产欧美日韩91| 日韩欧美在线一区| 欧美日韩性视频在线| 中文字幕国产精品久久| 欧美性色xo影院| 综合久久五月天| 国产精品成人品| 日产日韩在线亚洲欧美| 日韩成人中文字幕在线观看| 中文字幕日韩视频| 高清亚洲成在人网站天堂| 久久久久久成人| 国产成人高潮免费观看精品| 性夜试看影院91社区| 久久影视免费观看| 亚洲国产精品久久精品怡红院| 91在线视频免费| 久久久久免费精品国产| 欧美第一黄网免费网站| 亚洲国产成人精品女人久久久| 国产精品美女主播在线观看纯欲| 欧美午夜精品久久久久久浪潮| 两个人的视频www国产精品| 欧美精品xxx| 亚洲日本欧美日韩高观看| 亚洲成色777777在线观看影院| 欧美性xxxx极品hd欧美风情| 日韩av综合中文字幕| 色婷婷久久一区二区| 久久久久久久久亚洲| 国产成人亚洲综合91| 精品夜色国产国偷在线| 日韩精品在线观看网站| 91香蕉国产在线观看| 色偷偷噜噜噜亚洲男人| 欧美一级大片在线观看| 在线亚洲欧美视频| 激情久久av一区av二区av三区| 久久亚洲精品视频| 美女国内精品自产拍在线播放| 亚洲精品欧美一区二区三区| 久久精品视频播放| 国产精品视频男人的天堂| 麻豆一区二区在线观看| 亚洲精品一区在线观看香蕉| 日韩精品在线观看一区| 欧美另类高清videos| 亚洲视频网站在线观看| 亚洲精品国产精品国自产在线| 成人免费视频网|