Java-类库-Guava-EventBus
EventBus是Guava的事件处理机制,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现。对于事件监听和发布订阅模式,EventBus是一个非常优雅和简单解决方案,我们不用创建复杂的类和接口层次结构。
Observer模式是比较常用的设计模式之一,虽然有时候在具体代码里,它不一定叫这个名字,比如改头换面叫个Listener,但模式就是这个模式。手工实现一个Observer也不是多复杂的一件事,只是因为这个设计模式实在太常用了,Java就把它放到了JDK里面:Observable和Observer,从JDK 1.0里,它们就一直在那里。从某种程度上说,它简化了Observer模式的开发,至少我们不用再手工维护自己的Observer列表了。不过,如前所述,JDK里的Observer从1.0就在那里了,直到Java 7,它都没有什么改变,就连通知的参数还是Object类型。要知道,Java 5就已经泛型了。Java 5是一次大规模的语法调整,许多程序库从那开始重新设计了API,使其更简洁易用。当然,那些不做应对的程序库,多半也就过时了。这也就是这里要讨论知识更新的原因所在。今天,对于普通的应用,如果要使用Observer模式该如何做呢?答案是Guava的EventBus。
EventBus基本用法:
使用Guava之后, 如果要订阅消息, 就不用再继承指定的接口, 只需要在指定的方法上加上@Subscribe注解即可。代码如下:
消息封装类:
EventBus eventBus = new EventBus("test"); EventListener listener = new EventListener(); eventBus.register(listener); eventBus.post(new TestEvent(200)); eventBus.post(new TestEvent(300)); eventBus.post(new TestEvent(400)); System.out.println("LastMessage:"+listener.getLastMessage()); //输出信息 event message:200 Message:200 event message:300 Message:300 event message:400 Message:400 LastMessage:400
MultiListener的使用:
只需要在要订阅消息的方法上加上@Subscribe注解即可实现对多个消息的订阅,代码如下:
EventBus eventBus = new EventBus("test"); MultipleListener multiListener = new MultipleListener(); eventBus.register(multiListener); eventBus.post(new Integer(100)); eventBus.post(new Integer(200)); eventBus.post(new Integer(300)); eventBus.post(new Long(800)); eventBus.post(new Long(800990)); eventBus.post(new Long(800882934)); System.out.println("LastInteger:"+multiListener.getLastInteger()); System.out.println("LastLong:"+multiListener.getLastLong()); //输出信息 event Integer:100 event Integer:200 event Integer:300 event Long:800 event Long:800990 event Long:800882934 LastInteger:300 LastLong:800882934
Dead Event:
如果EventBus发送的消息都不是订阅者关心的称之为Dead Event。实例如下
说明:如果没有消息订阅者监听消息, EventBus将发送DeadEvent消息,这时我们可以通过log的方式来记录这种状态。
Event的继承:
如果Listener A监听Event A, 而Event A有一个子类Event B, 此时Listener A将同时接收Event A和B消息,实例如下:
Listener 类:
EventBus eventBus = new EventBus("test"); IntegerListener integerListener = new IntegerListener(); NumberListener numberListener = new NumberListener(); eventBus.register(integerListener); eventBus.register(numberListener); eventBus.post(new Integer(100)); System.out.println("integerListener message:"+integerListener.getLastMessage()); System.out.println("numberListener message:"+numberListener.getLastMessage()); eventBus.post(new Long(200L)); System.out.println("integerListener message:"+integerListener.getLastMessage()); System.out.println("numberListener message:"+numberListener.getLastMessage()); //输出类 Message:100 Message:100 integerListener message:100 numberListener message:100 Message:200 integerListener message:100 numberListener message:200
说明:在这个方法中,我们看到第一个事件(新的整数(100))是收到两个听众,但第二个(新长(200 l))只能到达NumberListener作为整数一不是创建这种类型的事件。可以使用此功能来创建更通用的监听器监听一个广泛的事件和更详细的具体的特殊的事件。
一个综合实例:
public UserThread(Socket connection, EventBus channel) { this.connection = connection; this.channel = channel; try { in = new BufferedReader(new InputStreamReader(connection.getInputStream())); out = new PrintWriter(connection.getOutputStream(), true); } catch (IOException e) { e.printStackTrace(); System.exit(1); @Subscribe public void recieveMessage(String message) { if (out != null) { out.println(message); System.out.println("recieveMessage:"+message); @Override public void run() { try { String input; while ((input = in.readLine()) != null) { channel.post(input); } catch (IOException e) { e.printStackTrace(); //reached eof channel.unregister(this); try { connection.close(); } catch (IOException e) { e.printStackTrace(); in = null; out = null; }
Socket connection = socket.accept(); UserThread newUser = new UserThread(connection, channel); channel.register(newUser); newUser.start(); } catch (IOException e) { e.printStackTrace(); }
说明:用telnet命令登录:telnet 127.0.0.1 4444 ,如果你连接多个实例你会看到任何消息发送被传送到其他实例
【JAVA】并发类库提供的线程池有哪几种? 线程是不能够重复启动的,创建或销毁线程存在一定的开销,所以利用线程池技术来提高系统资源利用效率,并简化线程管理,已经是非常成熟的选择。本篇博文的重点是 Java 并发类库提供的线程池有哪几种?
相关文章
- 8个华丽而实用的Java图表类库
- 彻底讲清 Java 的泛型(上)
- 2017年你不能错过的Java类库
- JAVA Synchronized (三) volatile 与 synchronized 的比较
- ABAP表生成Java实体Bean
- Java的I/O类库的基本架构
- java中的byte有什么作用?
- java 调优需要关闭的组建
- opencv4 java投影
- 关于Java中的整数类型值比较的疑问
- Guava:好用的java类库 学习小记
- 关于 Java 中 finally 语句块的深度辨析
- java值传递or引用传递解惑
- Java学习——基本数据类型
- Java线程死锁查看分析方法、工具,怎么检查死锁,死锁的原因是什么?
- Eclipse创建第一个Java项目
- Java模拟物流快递系统程序设计(此题仅仅实现类的继承与多态,后续增加接口部分)
- Java高并发专题之32、原子操作增强类LongAdder、LongAccumulator
- java-类库-Apache Commons
- Java-类库-Guava-Table
- Java-类库-Guava-Immutable(不可变)集合
- 查找附近网点geohash算法及实现 (Java版本号)
- 已解决java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String异常的
- 在Java API设计中,面向接口编程的思想,以及接口和工厂的关系
- Java中的Runnable、Callable、Future、FutureTask的区别和CompletionService的使用场景
- c++的class声明及相比java的更合理之处
- java访问共享文件夹
- 【杨辉三角(118-java)】