【EventBus】EventBus 源码解析 ( 事件发送 | postToSubscription 方法 | EventBus 线程模式处理细节 )

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 【EventBus】EventBus 源码解析 ( 事件发送 | postToSubscription 方法 | EventBus 线程模式处理细节 )

文章目录

一、事件发送 postSingleEventForEventType 方法

二、事件发送 postToSubscription 方法

三、事件发送 invokeSubscriber 方法





一、事件发送 postSingleEventForEventType 方法


首先 , 在同步代码块中 , 根据事件类型获取 Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType 成员变量中 , 指定 事件类型 键 Key 对应的 值 Value , 即 CopyOnWriteArrayList<Subscription> 集合 ;


每个集合元素都是 Subscription 对象 , 其中封装了 一个订阅者类 和 一个订阅方法 ;


     

synchronized (this) {
          // 根据事件类型获取 Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType 
          //  成员的值 , 即 CopyOnWriteArrayList<Subscription> 集合 
          //  每个集合元素都是 Subscription 对象 
          //  其中封装了 一个订阅者类 和 一个订阅方法 
            subscriptions = subscriptionsByEventType.get(eventClass);
        }


遍历上述集合 , 调用 postToSubscription 方法 , 进行事件传递后续操作 , 主要是执行 订阅者 中的 订阅方法 ;


             

// 调用 postToSubscription 方法 , 进行事件传递后续操作
                  //  主要是执行 订阅者 中的 订阅方法 
                    postToSubscription(subscription, event, postingState.isMainThread);



EventBus.postSingleEventForEventType 方法源码 :


public class EventBus {
    private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
    private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
        CopyOnWriteArrayList<Subscription> subscriptions;
        synchronized (this) {
          // 根据事件类型获取 Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType 
          //  成员的值 , 即 CopyOnWriteArrayList<Subscription> 集合 
          //  每个集合元素都是 Subscription 对象 
          //  其中封装了 一个订阅者类 和 一个订阅方法 
            subscriptions = subscriptionsByEventType.get(eventClass);
        }
        // 确保 CopyOnWriteArrayList<Subscription> 集合不为空 
        if (subscriptions != null && !subscriptions.isEmpty()) {
          // 遍历上述 CopyOnWriteArrayList<Subscription> 集合 
            for (Subscription subscription : subscriptions) {
              // 将当前的事件保存在 ThreadLocal 辅助类中 
                postingState.event = event;
                // 将当前的 订阅者 和 订阅方法 封装类 保存在 ThreadLocal 辅助类中 
                postingState.subscription = subscription;
                boolean aborted;
                try {
                  // 调用 postToSubscription 方法 , 进行事件传递后续操作
                  //  主要是执行 订阅者 中的 订阅方法 
                    postToSubscription(subscription, event, postingState.isMainThread);
                    aborted = postingState.canceled;
                } finally {
                    postingState.event = null;
                    postingState.subscription = null;
                    postingState.canceled = false;
                }
                if (aborted) {
                    break;
                }
            }
            return true;
        }
        return false;
    }
}





二、事件发送 postToSubscription 方法


从 Subscription subscription 参数中 , 获取订阅方法的线程模式 , 根据 【EventBus】Subscribe 注解分析 ( Subscribe 注解属性 | threadMode 线程模型 | POSTING | MAIN | MAIN_ORDERED | ASYNC) 博客的运行规则 , 执行线程 ;


订阅方法 的执行 , 实际上是通过反射 , 调用订阅方法 , 并传入指定类型的事件作为参数 , 完成的 ;


invokeSubscriber(subscription, event);


EventBus.postToSubscription 方法源码 :


public class EventBus {
    private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
      // 获取该 订阅方法 的线程模式 
        switch (subscription.subscriberMethod.threadMode) {
            case POSTING:
              // 不做线程切换 , 直接在发布线程中调用 
                invokeSubscriber(subscription, event);
                break;
            case MAIN:
                if (isMainThread) {
                  // 假如在主线程中 , 直接调用 
                    invokeSubscriber(subscription, event);
                } else {
                  // 假如发布线程是子线程 , 则将事件加入队列 , 通过 Handler 切换线程执行 
                    mainThreadPoster.enqueue(subscription, event);
                }
                break;
            case MAIN_ORDERED:
                if (mainThreadPoster != null) {
                    mainThreadPoster.enqueue(subscription, event);
                } else {
                    // temporary: technically not correct as poster not decoupled from subscriber
                    invokeSubscriber(subscription, event);
                }
                break;
            case BACKGROUND:
                if (isMainThread) {
                    backgroundPoster.enqueue(subscription, event);
                } else {
                    invokeSubscriber(subscription, event);
                }
                break;
            case ASYNC:
                asyncPoster.enqueue(subscription, event);
                break;
            default:
                throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
        }
    }
}






三、事件发送 invokeSubscriber 方法


通过反射调用订阅方法 ;


EventBus.invokeSubscriber 方法源码 :


public class EventBus {
    void invokeSubscriber(Subscription subscription, Object event) {
        try {
          // 通过反射调用 订阅方法 
            subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
        } catch (InvocationTargetException e) {
            handleSubscriberException(subscription, event, e.getCause());
        } catch (IllegalAccessException e) {
            throw new IllegalStateException("Unexpected exception", e);
        }
    }
}


目录
相关文章
|
19天前
|
安全 程序员 API
|
15天前
|
存储 设计模式 分布式计算
Java中的多线程编程:并发与并行的深度解析####
在当今软件开发领域,多线程编程已成为提升应用性能、响应速度及资源利用率的关键手段之一。本文将深入探讨Java平台上的多线程机制,从基础概念到高级应用,全面解析并发与并行编程的核心理念、实现方式及其在实际项目中的应用策略。不同于常规摘要的简洁概述,本文旨在通过详尽的技术剖析,为读者构建一个系统化的多线程知识框架,辅以生动实例,让抽象概念具体化,复杂问题简单化。 ####
|
23天前
|
数据采集 机器学习/深度学习 数据挖掘
10种数据预处理中的数据泄露模式解析:识别与避免策略
在机器学习中,数据泄露是一个常见问题,指的是测试数据在数据准备阶段无意中混入训练数据,导致模型在测试集上的表现失真。本文详细探讨了数据预处理步骤中的数据泄露问题,包括缺失值填充、分类编码、数据缩放、离散化和重采样,并提供了具体的代码示例,展示了如何避免数据泄露,确保模型的测试结果可靠。
35 2
|
26天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
19 3
|
26天前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
16 2
|
26天前
|
人工智能 数据挖掘 大数据
排队免单与消费增值模式:融合玩法与优势解析
排队免单模式通过订单排队、奖励分配、加速与退出机制等,结合消费增值模式中的积分制度、利润入池与积分增值等,共同提升消费者参与度和忠诚度,促进商家销售增长。具体包括订单自动排队、大单拆小单、异业联盟、线上线下融合及数据分析优化等进阶玩法,以及积分增值模型演算,形成一套完整的消费者激励体系。
|
26天前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
17 1
|
26天前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
31 1
|
26天前
|
Java
在Java多线程编程中,`wait()`和`notify()`方法的相遇如同一场奇妙的邂逅
在Java多线程编程中,`wait()`和`notify()`方法的相遇如同一场奇妙的邂逅。它们用于线程间通信,使线程能够协作完成任务。通过这些方法,生产者和消费者线程可以高效地管理共享资源,确保程序的有序运行。正确使用这些方法需要遵循同步规则,避免虚假唤醒等问题。示例代码展示了如何在生产者-消费者模型中使用`wait()`和`notify()`。
24 1
|
26天前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
34 1

推荐镜像

更多