当前位置:首页 > 全部子站 > IT > 思科认证

J2SE5.0用Executor灵活处理事件下发

来源:长理培训发布时间:2017-12-21 14:56:04

 百度广告

  每个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;
//...}public interface ClipListener extends EventListener {


final Collection listeners = new ArrayList();
addListener(ClipListener l) {
}
removeListener(ClipListener l) {
}
for(Iterator i = copyListeners();
ClipListener l = (ClipListener) i.next();
}
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() {






new DispatchableEventSupport(e);
d.addListener(l);
public void removeListener(ClipListener l) {
}
d.fireEvent(new DispatchableEvent
public void
l.clipUpdate(ce); //
});

















import org.recoil.pixel.executors.*;
DispatchableEventSupport(e);
J2SE5.0内建的Executor
新的J2SE 5.0类java.util.concurrent.Executors被用来创建复杂的线程池。你可以在池中配置线程数量,设置延迟或者周期调度。
例如,使用J2SE 5.0 Executor提供一个容纳5个事件下发线程的线程池
import org.recoil.pixel.dispatchable.*;
Executor tp = Executors.newFixedThreadPool(5);
DispatchableEventSupport(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 {
new DispatchableEventSupport();
addListener(ClipListener l, Executor e) {
}
d.fireEvent(new DispatchableEvent
public void
l.clipUpdate(ce);
});
[...]}
给SharedComponent增加侦听器的开发人员被强制为每一个侦听器定义一个Executor。假设每一个开发人员保持Executor为私有的,那么他的侦听器就有一定的分离量。这在他们使用基于线程池的Executor时非常有用。
如果所有相关的代码都在团队的控制下,那么SharedComponent是足够的,但这还不能完全解决等待问题。如果你因为使用遗留的或第三方代码而必须支持低效的侦听器时,你可以通过控制和强制每一个侦听器拥有自己的Executor来增加相互的独立性。
import org.recoil.pixel.dispatchable.*;
public class DefensiveComponent {
DispatchableEventSupport d =
public void addListener(ClipListener l) {
d.addListener(l, e);
public void removeListener(ClipListener l) {
}
d.fireEvent(new DispatchableEvent
public void
l.clipUpdate(ce);
});
[...]}
DefensiveComponent为每一个增加的侦听器附加对应的事件下发线程,这就分离了低效的侦听器并且确保侦听器可以被独立的处理;高效的侦听器不需要等待低效的。这种策略是简单而安全的,但也是高代价的,因为他必须创建和销毁许多线程。在大部分情况下,需要通过Executors创建合理大小的线程池也平衡独立性和代价。
同步多事件流
DispatchableEvent允许你通过一个简单的Executor多元化相应事件来同步来自不同异步资源的事件。
例如,考虑一个支持鼠标和语音识别的多模画板应用。
通常语音识别在一断语音被识别时派发一个事件。想像用户选择一个图形然后说"删除"。显然我们希望鼠标事件被首先处理,否则可能会删除错误的对象。一种简单地解决这个问题的方法是使用AWTExecutor来下发语音事件,他会在事件被收到时将其放在AWT事件队列中,确保首先处理MouseEvents。
这个想法可以扩展到更多的异步事件流,通过将每一个事件源作为引用放到一个共享的基于队列的Executor中。每一个事件根据顺序放在队列中,交叉地下发。
小结
这篇文章专注于可能发生在侦听器范例中的问题。我们看到一个简单的派发类库如何通过Executors被用来自定义事件下发。使用不同的策略你可以将你的组件与子系统(如AWT)集成,你可以通过允许客户定义使用的Executor来给予他们更多的选择,或者你可以从另一方面来分离低效的侦听器来防止等待。

责编:罗莉

发表评论(共0条评论)
请自觉遵守互联网相关政策法规,评论内容只代表网友观点,发表审核后显示!

国家电网校园招聘考试直播课程通关班

  • 讲师:刘萍萍 / 谢楠
  • 课时:160h
  • 价格 4580

特色双名师解密新课程高频考点,送国家电网教材讲义,助力一次通关

配套通关班送国网在线题库一套

课程专业名称
讲师
课时
查看课程

国家电网招聘考试录播视频课程

  • 讲师:崔莹莹 / 刘萍萍
  • 课时:180h
  • 价格 3580

特色解密新课程高频考点,免费学习,助力一次通关

配套全套国网视频课程免费学习

课程专业名称
讲师
课时
查看课程
在线题库
面授课程更多>>
图书商城更多>>
在线报名
  • 报考专业:
    *(必填)
  • 姓名:
    *(必填)
  • 手机号码:
    *(必填)
返回顶部