guava EventBus 学习一

背景

event bus 数据总线, 数据发送者发送信息到总线, 数据接收者从总线接收数据. 大概相似于下飞机去取行李的时候, 旅客在行李传送带旁边等候本身的行李, 在这个场景下, 飞机至关于发送者, 旅客为接收者, 传送带就是咱们的数据总线, 旅客上飞机就是一个注册的过程. 与咱们后面准备学习的guava中的EventBus不一样的是, 旅客是本身"拉取"的行李, 可是在guava中是总线根据注册信息推送消息到订阅者. 更恰当的例子是去餐厅吃饭, 顾客进入餐厅并坐下, 这就是注册. 顾客点餐这就是订阅. 厨师作出来的菜会根据点餐列表, 将菜送到顾客面前, 这就是消息的发送, 若是多个顾客点了同一道菜, 那么厨师会作多道菜(? 多个副本?), 并分别送到对应的顾客面前. 给个人感受就像一个系统内部的一个MQ~ 废话到此结束, 下面经过demo了解下如何使用guava中的EventBus数据库

EventBus

环境

guava版本网络

<dependency>
    <artifactId>guava</artifactId>
    <groupId>com.google.guava</groupId>
    <version>28.0-jre</version>
</dependency>

jdk1.8 Junit4并发

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

驾照

guava的EventBus使用上突出一个简单, 咱们只须要在EventBus上注册监听, 而后往EventBus发送消息, 最后根据消息类型将消息发给监听者. 代码代码~搞起搞起~异步

// 创建一个数据工具类, 你是司机, 往哪开你说了算~
public class AwesomeEventBusDriver {

    // 准备好车
    private static EventBus eventBus = new EventBus();

    // 上车
    public static void register(Object object) {
        eventBus.register(object);
    }
    // 发车
    public static void publishAnything(Object object) {
        eventBus.post(object);
    }
}
// 学员
public class AwesomeStudent {

    // 发车了要告诉我
    @Subscribe
    public void listen(String obj) {

        System.out.println("科一" + obj);
    }
}

跑起来~async

@Test
public void 科一() {

    AwesomeEventBusDriver.register(new AwesomeStudent());
    AwesomeEventBusDriver.publishAnything("经过~");
}

Ok~ 科一过了 如今是科二, 咱们不光想知道过没过, 还要知道得了几分ide

public class AwesomeStudent_1 {

    @Subscribe
    public void 科二(String obj) {

        System.out.println("科二" + obj);
    }

    @Subscribe
    public void 科二分数(Integer obj) {

        System.out.println("科二分数" + obj);
    }
}

考科二拉工具

@Test
public void 科二() {

    AwesomeEventBusDriver.register(new AwesomeStudent_1());
    AwesomeEventBusDriver.publishAnything("经过~");
    AwesomeEventBusDriver.publishAnything(100);
}

能够看到不一样的数据类型会进入不一样的方法执行. ok, 科二满分经过. 还有考科三的同窗一块儿查成绩post

public class AwesomeStudent_2 {

    @Subscribe
    public void 科三分数(Double obj) {

        System.out.println("科三" + obj);
    }
}
@Test
public void 科三() {

    AwesomeEventBusDriver.register(new AwesomeStudent_1());
    AwesomeEventBusDriver.register(new AwesomeStudent_2());
    AwesomeEventBusDriver.publishAnything(100);
    AwesomeEventBusDriver.publishAnything(90.5);
}

多个类和多个方法区别不大. 最后科四~学习

// 教练来喽
public class AwesomeCoach {

    @Subscribe
    public void all(DeadEvent event) {

        System.out.println(event);
    }
}
// 自定义了两个类
public class AwesomeMessageEvent {

    private String message;

    public AwesomeMessageEvent(String message){
        this.message = message;
    }

    @Override
    public String toString() {
        return "AwesomeEvent{" +
                "message='" + message + '\'' +
                '}';
    }
}

public class AwesomeMoneyEvent {

    private String message;

    public AwesomeMoneyEvent(String message){
        this.message = message;
    }

    @Override
    public String toString() {
        return "AwesomeMoneyEvent{" +
                "message='" + message + '\'' +
                '}';
    }
}
@Test
public void 科四() {

    AwesomeEventBusDriver.register(new AwesomeStudent_1());
    AwesomeEventBusDriver.register(new AwesomeStudent_2());
    AwesomeEventBusDriver.register(new AwesomeCoach());
    AwesomeEventBusDriver.publishAnything(100);
    AwesomeEventBusDriver.publishAnything(90.5);
    AwesomeEventBusDriver.publishAnything(new AwesomeMessageEvent("教练通融下"));
    AwesomeEventBusDriver.publishAnything(new AwesomeMoneyEvent("教练这是点小意思~"));
}

运行后会发现coach会接收到测试中最后两个自定义的消息类, 这就是DeadEvent的做用, 它的意思就是接收没有订阅者订阅的消息.测试

好了, 驾照拿到, 咱们来总结下 1 消息总线EventBus有点像MQ. 2 EventBus使用很是简单, 咱们只须要提供三部分: EventBus类, 订阅者(@Subscribe注解方法), 消息类(若是须要监听的话). 而后经过EventBus注册订阅者, 并发送消息给订阅者. 3 消息路由依据消息类型, 若是有多个订阅者就会发送多份消息. 若是发送的消息没有对应的订阅者, 则该消息会包含在DeadEvent中, 咱们订阅该类消息, 专门处理没有人处理的消息. 若是有订阅者订阅的是Object类消息, 也就不会存在DeadEvent消息了.

上路

拿到驾照立刻上路搞起~

public class AwesomeAsyncSubscriber {

    // 我要上内存的车
    @Subscribe
    public void cpu(Integer money) {

        System.out.println("cpu :" + money);
    }

    // 我要上笔记本的车
    @Subscribe
    public void laptop(Long money) throws InterruptedException {

        int count = 3;
        while (count > 0) {
            count--;
            Thread.sleep(1000);
        }
        System.out.println("laptop :" + money);
    }

    // 我要上不能说的车
    @Subscribe
    public void poxn(String seed) throws InterruptedException {

        System.out.println("poxn " + seed);
        System.out.println("downloading ...0%");
        int count = 5;
        while (count > 0) {
            count--;
            Thread.sleep(1000);
        }

        System.out.println("99%...100%");
    }
}

开车~

@Test
public void 同步开车() {

    AwesomeEventBusDriver.register(new AwesomeAsyncSubscriber());

    AwesomeEventBusDriver.publishAnything("xxxx");
    AwesomeEventBusDriver.publishAnything(2990);
    AwesomeEventBusDriver.publishAnything(200L);
}

运行后, 敏锐的你确定发现了...种子很差下啊~ 不是网速不行就是资源不行, 下不下来后面的同志就没办法接收到消息. 这就是EventBus的同步模式. 咱们应该尽可能避免在同步模式中使用耗时操做, 好比数据库操做, 网络请求等, 或者咱们能够在接收到消息后异步执行耗时操做, 再或者咱们能够直接异步接收消息. 修改下老司机

public class AwesomeEventBusDriver {

    // 增长异步总线; 开两个线程
    private static EventBus asyncEventBus = new AsyncEventBus(Executors.newFixedThreadPool(2));

    private static EventBus eventBus = new EventBus();
    // 注册到异步总线
    public static void registerAsync(Object object) {
        asyncEventBus.register(object);
    }
    // 发送消息到异步总线
    public static void publishAsyncAnything(Object object) {
        asyncEventBus.post(object);
    }

    public static void register(Object object) {
        eventBus.register(object);
    }

    public static void publishAnything(Object object) {
        eventBus.post(object);
    }
}

异步发车

@Test
public void 异步开车() throws InterruptedException {

    AwesomeEventBusDriver.registerAsync(new AwesomeAsyncSubscriber());

    AwesomeEventBusDriver.publishAsyncAnything("xxxx");
    AwesomeEventBusDriver.publishAsyncAnything(200L);
    AwesomeEventBusDriver.publishAsyncAnything(2990);

    int i = 0;
    while (AwesomeAsyncSubscriber.running) {

        Thread.sleep(1000);
        i++;
        System.out.println(i + "s");
    }
}

上路总结 1 订阅者接收消息的顺序是和消息发送的顺序一致的(只是表现是这样的, 下一篇从源码中一探究竟) 2 同步发送时, 只有当订阅者处理完消息后才会发送下一个消息 3 异步发送时, 同时发送消息数量取决于定义EventBus时指定的线程数.

总结

以上经过几个简单的例子, 讲了下EventBus的简单使用, 固然学习最好的办法仍是理论加实践, 后面会在项目中加入EventBus, 用来处理关键节点的日志表记录(就算用错了, 就是少几条日志, 还能接受~). 为了更好的使用, 下一篇会从阅读关键源码, 了解代码执行逻辑. 今天就这样, 下次带你上秋名山~.~

相关文章
相关标签/搜索