您的位置 首页 java

事件驱动模型

事件驱动和消息驱动

消息驱动和事件驱动很类似,都是先有一个事件,然后产生一个相应的消息,再把消息放入消息队列,由需要的项目获取。他们的区别是消息是谁产生的

消息驱动 :鼠标管自己点击不需要和系统有过多的交互,消息由系统(第三方)循环检测,来捕获并放入消息队列。消息对于点击事件来说是被动产生的,高内聚。

事件驱动 :鼠标点击产生点击事件后要向系统发送消息 “我点击了” 的消息,消息是主动产生的。再发送到消息队列中。事件往往会将事件源包装起来。


事件驱动往往和轮询机制相关,它们通常被统称为 event loop 。重点在于并不会给每一个事件分配一个轮询来探知其变化,而是设置一个中央轮询中心,用这个轮询中心去轮询每个注册的对象。轮询中心一旦检测到了注册其中的对象有事件发生,那么就通知对此事件感兴趣的对象。而对此事件感兴趣的对象此时会调用的方法被称为回调函数。


有时也把事件驱动按照实现方式的不同进行区分(个人并不认为很准确,但是很多人都这么说):

  • 轮询方式
    线程不断轮询访问相关 事件发生源 有没有发生事件,有发生事件就调用事件处理逻辑。
  • 事件驱动方式
    事件发生时主线程把事件放 入事件队列 ,在另外线程不断循环消费事件列表中的事件,调用事件对应的处理逻辑处理事件。事件驱动方式也被称为消息通知方式,其实是 设计模式中观察者模式 的思路。

事件驱动模型可以用下图表示(来源于《Software Architecture Patterns》):

事件驱动模型

主要包括 4 个基本组件:

  • 事件队列(event queue) :接收事件的入口,存储待处理事件
  • 分发器(event mediator) :将 不同的事件 分发到不同的业务逻辑单元
  • 事件通道(event channel) :分发器与处理器之间的联系渠道
  • 事件处理器(event processor) :实现业务逻辑,处理完成后会发出事件,触发下一步操作

比如说在 Java 的 Socket NIO 模型中,SocketChannel 总是将自身注册为对可读、可写事件感兴趣,ServerSocketChannel 却往往将自己注册为对有一个新的 TCP 连接请求感兴趣。不同的类型的对象可以以不同的兴趣注册到同一个分发器中,分发器既需要能够辨别发生了的不同事件,又需要能够将不同的事件分派给不同的事件通道。因为分发器具备这种为有着不同兴趣的不同对象服务的能力,所以分发器仅仅需要占一个线程。

另一个问题是事件处理器如何知道事件发生了?事件处理器就像人一样,人通过每天时不时地看看报纸、看看手机 APP,”时不时地看“这个动作是由人主动发出的,这是最关键的。处理器需要一个其独享的线程,在这个线程中进行检查是否发生了新的事件,这个线程在没有被通知时是阻塞的,一旦 Event Channel 传来了新的事件,事件处理器就不再阻塞。

所以,有一个单线程不阻塞地进行轮询事件队列,一旦发现事件发生了,就通过事件分发器,将包装好的事件通过事件通道传给事件处理器。而每个事件处理器也单独占据一个线程,如果此时没有事件传递过来,其就会阻塞,直到事件传递过来。

事件队列和事件处理器除了在各自的线程模型是否阻塞上有所区别以外,在实现者上也有所区别。通常事件队列包括分发器、事件通道都是由类库替我们完成的,而事件处理器的逻辑则需要更偏向业务的程序员完成。

——————————————————–

转载自:

文章来源:智云一二三科技

文章标题:事件驱动模型

文章地址:https://www.zhihuclub.com/200019.shtml

关于作者: 智云科技

热门文章

网站地图