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

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 【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);
        }
    }
}


目录
相关文章
|
6天前
|
Java
解析Java线程池:参数详解与执行流程
解析Java线程池:参数详解与执行流程
9 1
|
3天前
|
Java 开发者
线程通信的方法和实现技巧详解
线程通信的方法和实现技巧详解
|
3天前
|
Java
线程间通信的几种方法
线程间通信的几种方法
|
10天前
|
Arthas 监控 Java
深入解析与解决高并发下的线程池死锁问题
在高并发的互联网应用中,遇到线程池死锁问题导致响应延迟和超时。问题源于库存服务的悲观锁策略和线程池配置不当。通过以下方式解决:1) 采用乐观锁(如Spring Data JPA的@Version注解)替换悲观锁,减少线程等待;2) 动态调整线程池参数,如核心线程数、最大线程数和拒绝策略,以适应业务负载变化;3) 实施超时和重试机制,减少资源占用。这些改进提高了系统稳定性和用户体验。
38 2
|
10天前
|
Java
Java多线程中notifyAll()方法用法总结
Java多线程中notifyAll()方法用法总结
|
14天前
|
Java
JAVA多线程深度解析:线程的创建之路,你准备好了吗?
【6月更文挑战第19天】Java多线程编程提升效率,通过继承Thread或实现Runnable接口创建线程。Thread类直接继承启动简单,但限制多继承;Runnable接口实现更灵活,允许类继承其他类。示例代码展示了两种创建线程的方法。面对挑战,掌握多线程,让程序高效运行。
|
1天前
|
安全 Java 程序员
Java多线程编程最佳实践与常见问题解析
Java多线程编程最佳实践与常见问题解析
|
2天前
|
Java 开发者
线程通信的方法和实现技巧详解
线程通信的方法和实现技巧详解
|
4天前
|
消息中间件 Java 数据安全/隐私保护
线程间通信的方法与比较分析
线程间通信的方法与比较分析
|
4天前
|
Java
使用notifyAll唤醒所有等待线程的方法与比较
使用notifyAll唤醒所有等待线程的方法与比较

推荐镜像

更多