Android EventBus使用方法与底层原理详解

EventBus 是什么?

EventBus 是一个基于发布/订阅(Publish/Subscribe) 模式的开源库(主要由 greenrobot 开发维护)。它的核心目的是简化 Android 应用中不同组件(如 Activity, Fragment, Service, Thread 等)之间的通信。它通过一个中央事件总线(Central Event Bus)来传递事件(Event 对象),允许组件订阅它们关心的事件类型,并在事件发生时自动接收通知。这显著降低了组件间的耦合度。

核心概念

  1. 事件 (Event): 一个普通的 Java 对象(POJO),代表需要传递的消息或通知。事件本身不包含逻辑,只是数据的载体。可以是任何类,比如 MessageEvent, DataUpdateEvent, UserLoggedInEvent 等。
  2. 发布者 (Publisher): 任何需要通知其他组件发生了某事的对象。它创建一个事件对象并通过 EventBus 实例post(event) 发布该事件到总线上。
  3. 订阅者 (Subscriber): 对特定类型事件感兴趣的对象。它包含一个或多个用 @Subscribe 注解标记的方法(称为事件处理方法)。这些方法定义了当特定事件被发布时应该执行的逻辑。
  4. 事件总线 (EventBus): 单例(通常通过 EventBus.getDefault() 获取)或自定义实例。它负责:
    • 维护所有订阅者及其感兴趣的事件类型的注册表。
    • 接收发布者发送的事件。
    • 根据事件类型查找所有匹配的订阅者。
    • 在正确的线程(根据订阅方法指定的 ThreadMode)上调用订阅者的事件处理方法。

一、 使用方法 (非常详细)

1. 添加依赖 (以 Gradle 为例)

在 app 模块的 build.gradle 文件中添加最新版本的 EventBus 依赖(请查看 Maven Central 获取最新版本):

dependencies {implementation 'org.greenrobot:eventbus:3.3.1' // 检查最新版本
}

2. 定义事件 (Event)

创建一个简单的 Java 类来表示你想要传递的数据或通知。

public class MessageEvent {public final String message;public MessageEvent(String message) {this.message = message;}
}

3. 准备订阅者 (Subscriber)

在需要接收事件的组件(如 Activity、Fragment、Service 或任何普通对象)中:

  • 注册/注销: 组件必须在开始接收事件前向 EventBus 注册自己,并在不再需要接收事件(或生命周期结束时)注销自己,以避免内存泄漏和无效调用。
    • 注册: 通常在 onStart()onResume() 中进行。
    • 注销: 通常在 onStop()onPause() 中进行(选择与注册对称的生命周期方法)。对于 Fragment,onCreateView/onDestroyView 也是常见选择。
public class MyActivity extends AppCompatActivity {@Overrideprotected void onStart() {super.onStart();EventBus.getDefault().register(this); // 注册当前 Activity 作为订阅者}@Overrideprotected void onStop() {super.onStop();EventBus.getDefault().unregister(this); // 注销当前 Activity}// ... 其他代码 ...
}
  • 声明事件处理方法: 使用 @Subscribe 注解标记一个公共方法(方法名任意)。该方法的参数类型决定了它订阅哪种事件。注解可以指定 threadModesticky 属性。
    • threadMode (必选): 指定事件处理方法在哪个线程执行。这是 EventBus 的核心优势之一。
      • ThreadMode.POSTING (默认): 在事件发布所在的线程调用。最快,避免线程切换开销。小心:如果发布者在主线程发布,你在这里不能执行耗时操作;如果发布者在后台线程发布,你在这里不能更新UI。
      • ThreadMode.MAIN: 在 Android 的主线程 (UI 线程) 调用。安全更新 UI。如果事件是在主线程发布的,方法会立即执行;否则,事件会被放入主线程队列等待处理。
      • ThreadMode.MAIN_ORDERED: 类似于 MAIN,但事件在队列中有序执行MAIN 可能在某些情况下插队)。通常使用 MAIN 即可。
      • ThreadMode.BACKGROUND: 在后台线程调用。如果事件是在非主线程发布的,就在该线程直接调用;如果是在主线程发布的,EventBus 会使用一个单一线程的后台线程池来调用该方法。适合执行轻量级后台操作
      • ThreadMode.ASYNC: 在独立的、非主线程、非发布者线程调用。EventBus 使用一个线程池来调用这些方法。适合执行耗时操作(如网络请求、数据库大查询),不会阻塞发布线程或主线程。
    • sticky (可选,默认 false): 是否处理粘性事件 (Sticky Event)。如果设为 true,那么即使事件是在该订阅者注册之前发布的,只要该粘性事件还在总线上,订阅者注册后会立即收到该事件的最新一次发布。非常适用于需要获取“最新状态”的场景(如当前登录用户信息、网络状态)。
// 示例1:在主线程处理 MessageEvent
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {// 安全更新UItextView.setText(event.message);
}// 示例2:在后台线程处理 DataLoadedEvent
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void handleDataLoaded(DataLoadedEvent event) {// 处理数据,比如保存到数据库(轻量级操作)saveDataToDatabase(event.data);
}// 示例3:处理粘性事件 UserLoggedInEvent
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void onUserLoggedIn(UserLoggedInEvent event) {// 更新UI显示当前登录用户信息updateUserProfile(event.user);
}

4. 发布事件 (Publisher)

在任何需要通知其他组件的地方(任何类中),获取 EventBus 实例并调用 post(Object event) 方法。event 对象就是你要传递的事件实例。

// 在某个按钮点击事件或网络请求回调中
public void someMethodThatTriggersEvent() {// 创建事件对象MessageEvent event = new MessageEvent("Hello EventBus!");// 发布事件到总线EventBus.getDefault().post(event);
}// 发布粘性事件 (会一直保留在总线上直到被覆盖或手动移除)
public void postStickyEvent() {UserLoggedInEvent event = new UserLoggedInEvent(currentUser);EventBus.getDefault().postSticky(event);
}

5. 处理粘性事件 (Sticky Events) 的额外操作

  • 获取最新粘性事件: 使用 EventBus.getStickyEvent(Class<T> eventType) 可以在订阅者注册前或任何地方手动获取特定类型的最新粘性事件。
  • 移除粘性事件: 使用 EventBus.removeStickyEvent(T event)EventBus.removeStickyEvent(Class<T> eventType) 手动移除粘性事件。
// 在注册订阅者之前,检查是否有最新的登录信息
UserLoggedInEvent stickyEvent = EventBus.getDefault().getStickyEvent(UserLoggedInEvent.class);
if (stickyEvent != null) {// 立即使用最新用户信息更新UI或状态updateUserProfile(stickyEvent.user);
}

6. 事件继承

EventBus 支持事件继承。如果一个订阅者订阅了父类事件类型(如 BaseEvent),那么当发布者发布任何该父类的子类事件(如 SpecificEvent extends BaseEvent)时,该订阅者也会接收到通知。这可以用于创建更通用的事件处理器。

7. 优先级 (priority)

@Subscribe 注解中可以设置 priority 属性(整数,默认 0)。数值越大,优先级越高。优先级高的订阅者方法会在优先级低的之前接收到事件。如果优先级相同,顺序不确定。注意: 只有在同一个 ThreadMode 下,优先级才生效。优先级通常用于拦截或修改事件(高优先级订阅者可以调用 EventBus.cancelEventDelivery(event) 来阻止事件继续传递给低优先级订阅者)。

@Subscribe(threadMode = ThreadMode.MAIN, priority = 1)
public void onHighPriorityEvent(MyEvent event) {// 高优先级处理if (shouldCancel(event)) {EventBus.getDefault().cancelEventDelivery(event); // 取消事件传递}
}

8. 混淆配置 (Proguard/R8)

如果使用代码混淆,需要在 Proguard 规则文件 (proguard-rules.pro) 中添加以下配置,以确保 @Subscribe 注解方法在运行时能被正确找到(如果使用索引加速则可能不需要,但加上更保险):

-keepattributes *Annotation*
-keepclassmembers class * {@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
# 如果使用了索引加速 (EventBusAnnotationProcessor)
-keep class org.greenrobot.eventbus.** { *; }

9. 索引加速 (EventBusAnnotationProcessor) - 推荐

EventBus 3 引入了索引加速,在编译时通过 APT (Annotation Processing Tool) 生成一个索引类,列出所有 @Subscribe 方法及其信息(事件类型、线程模式、优先级等)。这避免了在 App 首次运行时使用反射扫描所有类查找订阅方法,大大提高了注册速度和启动性能,并减少了运行时方法查找的开销。

启用步骤:

  1. 添加注解处理器依赖:

    dependencies {implementation 'org.greenrobot:eventbus:3.3.1'annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.3.1' // 与 eventbus 版本一致
    }
    
  2. 配置索引选项 (可选但推荐): 在 app 模块的 build.gradle 中指定生成的索引类名:

    android {defaultConfig {javaCompileOptions {annotationProcessorOptions {arguments = [ eventBusIndex : 'com.yourpackage.MyEventBusIndex' ]}}}
    }
    
  3. 在 Application 中设置索引: 在自定义 Application 类的 onCreate() 中配置 EventBus 使用生成的索引:

    public class MyApp extends Application {@Overridepublic void onCreate() {super.onCreate();// 使用索引构建 EventBus 实例 (替代默认反射查找)EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();// 现在 EventBus.getDefault() 已经使用了索引}
    }
    

    或者在需要使用 EventBus 的地方手动创建带索引的实例:

    EventBus eventBus = EventBus.builder().addIndex(new MyEventBusIndex()).build();
    

二、 应用场景

EventBus 特别适合解决以下通信难题:

  1. Fragment 间通信: 两个 Fragment 之间没有直接引用。Fragment A 发布事件,Fragment B 订阅并处理。比通过 Activity 中转或接口回调更简洁。
  2. Activity 与 Service 通信: Service 后台完成任务(如下载完成、播放状态改变)后发布事件,Activity 订阅并更新UI。
  3. 后台线程与 UI 线程通信: 在后台线程(如网络请求、数据库操作)中完成任务后发布事件,订阅者指定 ThreadMode.MAIN 安全更新UI。
  4. 跨层通信: 深度嵌套的组件(如 Adapter 中的 ViewHolder)需要通知顶层的 Activity 或 Fragment 执行某些操作(如打开新界面)。
  5. 广播全局状态变化: 用户登录/登出、网络连接状态变化、语言切换、主题更改等全局状态变更。使用粘性事件尤其方便,新启动的组件能立即获取最新状态。
  6. 替代部分 Intent/BroadcastReceiver: 对于应用内部通信,EventBus 比系统广播更轻量、更快速、类型更安全(避免 Intent 的 key 字符串硬编码)。
  7. 解耦业务逻辑与 UI 更新: 业务逻辑模块(如 Presenter, ViewModel, Interactor)处理完逻辑后发布事件,UI 层(Activity/Fragment)订阅事件并只负责展示,实现更好的关注点分离。
  8. 组件化/模块化通信: 不同模块之间通过定义和发布/订阅公共事件接口进行通信,减少模块间的直接依赖。

三、 底层原理 (深入解析)

EventBus 的核心在于高效地管理订阅关系和在正确线程上派发事件。以下是其核心机制:

  1. 订阅者注册 (register(Object subscriber)):

    • 方法查找 (运行时 / 编译时):
      • 运行时 (默认,无索引): 使用反射遍历 subscriber 对象的所有方法,查找所有被 @Subscribe 注解标记的公共方法。提取方法参数类型(即订阅的事件类型)、ThreadMode、优先级、是否粘性等信息。
      • 编译时 (使用索引): 编译期间 EventBusAnnotationProcessor 扫描所有类,找出所有 @Subscribe 方法,生成一个索引类(如 MyEventBusIndex)。注册时直接从这个索引类中查找 subscriber 的类名对应的所有订阅方法信息,避免了耗时的运行时反射扫描
    • 构建订阅关系映射: EventBus 内部维护一个核心数据结构:Map<Class<?>, CopyOnWriteArrayList<Subscription>>
      • Key (Class<?>): 事件类型(event.getClass())。
      • Value (CopyOnWriteArrayList<Subscription>): 一个线程安全的列表,存储了所有订阅了该事件类型的 Subscription 对象。
      • Subscription 对象封装了:订阅者对象 (subscriber)、订阅者方法 (SubscriberMethod - 包含方法对象、ThreadMode、优先级、是否粘性)。
    • 对于找到的每个订阅方法,根据其订阅的事件类型,将封装好的 Subscription 对象添加到上述映射表中对应事件类型的列表中。列表根据 Subscription 的优先级(priority)排序。
  2. 事件发布 (post(Object event)):

    • 获取当前线程状态: post() 方法首先获取当前线程的 PostingThreadState 对象(一个 ThreadLocal 变量)。PostingThreadState 包含:
      • eventQueue:当前线程待处理的事件队列。
      • isPosting:标识当前是否正在派发事件。
      • isMainThread:标识当前线程是否是主线程。
      • subscription:当前正在处理的事件对应的订阅信息(用于 cancelEventDelivery)。
    • 入队: 将传入的 event 对象加入到当前线程的 eventQueue 中。
    • 事件派发循环: 如果当前线程不在派发过程中 (!isPosting),则开始处理队列:
      • 设置 isPosting = true
      • 循环从队列头部取出事件。
      • 调用 postSingleEvent(event, postingState) 处理单个事件。
      • 处理完队列所有事件后,重置状态 isPosting = false
  3. 单个事件处理 (postSingleEvent):

    • 查找订阅者: 根据事件的运行时类 (event.getClass()),从订阅关系映射表中查找对应的 Subscription 列表。
    • 处理事件继承 (可选): 如果启用了事件继承(默认启用),还会查找该事件类的所有父类和接口对应的订阅者列表,并将所有找到的订阅者合并到一个总的列表中(去重)。
    • 遍历订阅者并派发 (postToSubscription): 对于找到的每一个 Subscription
      • 检查订阅者是否已注销(弱引用失效)。
      • 根据 ThreadMode 决定执行方式:
        • POSTING直接调用。在当前发布线程直接通过反射(或 MethodHandle)调用订阅者方法。最快,但需注意线程安全。
        • MAIN / MAIN_ORDERED
          • 如果当前是主线程:直接调用(MAIN_ORDERED 会确保按入队顺序)。
          • 如果当前不是主线程:将调用包装成一个 Runnable,通过 mainThreadPoster(通常是 HandlerPoster,它内部持有一个关联到主线程 Looper 的 Handler)发送到主线程的消息队列中排队执行。
        • BACKGROUND
          • 如果当前不是主线程:直接调用(在当前后台线程)。
          • 如果当前是主线程:将调用包装成 Runnable,通过 backgroundPoster(通常是 BackgroundPoster,它内部使用一个单线程的线程池 ExecutorService)提交到后台线程执行。
        • ASYNC总是将调用包装成 Runnable,通过 asyncPoster(通常是 AsyncPoster,它内部使用一个通用的线程池 ExecutorService)提交执行,与发布线程和当前线程无关。
      • 优先级处理: 在同一个 ThreadMode 下,列表已经按优先级排序,高优先级的 Subscription 会先被处理。高优先级订阅者可以通过 cancelEventDelivery(event) 取消事件,阻止后续低优先级订阅者收到该事件。cancelEventDelivery 只能在 POSTING 模式下调用,因为它需要直接操作当前派发流程。
  4. 粘性事件 (postSticky(Object event)):

    • 存储: EventBus 内部维护一个 Map<Class<?>, Object> 用于存储粘性事件。Key 是事件类型,Value 是该类型最新的粘性事件对象。发布粘性事件时,会先更新这个 Map(覆盖旧事件)。
    • 发布: 然后像普通事件一样调用 post(event) 进行派发。
    • 新订阅者处理: 当一个新的订阅者调用 register() 时,如果它声明了 sticky=true 的事件处理方法:
      • 注册过程完成后,EventBus 会检查粘性事件 Map。
      • 对于该订阅者每个声明为 sticky=true 的事件类型,从 Map 中取出最新的粘性事件(如果存在)。
      • 然后按照正常的派发逻辑(根据 ThreadMode)调用该订阅者的对应方法,就好像这个事件刚刚发布一样。
  5. 注销 (unregister(Object subscriber)):

    • 遍历内部订阅关系映射表 (Map<Class<?>, CopyOnWriteArrayList<Subscription>>)。
    • 对于每个事件类型的订阅者列表,移除所有 subscription.subscriber 等于传入的 subscriberSubscription 对象。
    • 移除后,该订阅者对象将不再接收任何事件。
  6. 线程安全:

    • 核心数据结构 Map<Class<?>, CopyOnWriteArrayList<Subscription>> 使用 ConcurrentHashMap 或其变体保证键的并发访问安全。CopyOnWriteArrayList 保证了单个事件类型订阅者列表的线程安全(读无锁,写复制)。
    • 使用 ThreadLocal (PostingThreadState) 管理每个线程的派发状态。
    • 不同 ThreadMode 的派发器 (HandlerPoster, BackgroundPoster, AsyncPoster) 内部使用队列和锁/Handler/线程池来保证任务的有序执行和线程安全。
    • 注册/注销操作通常是同步的(内部有锁),应尽量在主线程或确保线程安全的环境下调用。

关键优化点:

  • 索引加速: 极大提升注册速度,避免首次运行时反射扫描。
  • CopyOnWriteArrayList: 读多写少场景(事件派发是高频读,注册/注销是相对低频写)性能好,读操作完全无锁。
  • 线程局部变量 (PostingThreadState): 高效管理每个线程的事件队列和派发状态。
  • 按需线程切换: 只在需要时才将任务派发到其他线程(通过 Handler 或 Executor)。
  • 弱引用: Subscription 持有订阅者对象的弱引用 (WeakReference)。这非常重要!它确保如果订阅者对象(如 Activity)被垃圾回收(例如用户关闭了 Activity 但忘记调用 unregister()),Subscription 中的弱引用会自动失效。EventBus 在派发事件时会检查弱引用是否有效,无效则跳过或移除该 Subscription,从而自动防止了因忘记注销而导致的内存泄漏。这是 EventBus 设计中的一个关键安全机制。(注意:虽然弱引用提供了保护,但最佳实践仍是显式 unregister() 以保持代码清晰和及时释放资源)。

总结:

EventBus 通过高效的发布/订阅机制、强大的线程模式支持、粘性事件特性以及底层精心的设计(映射表、ThreadLocal、弱引用、线程池/Handler),为 Android 开发提供了一种极其便捷、灵活且相对安全的组件间通信方式。它特别擅长解耦跨组件、跨线程的通信需求。理解其底层原理(尤其是订阅关系管理、线程派发逻辑和弱引用机制)对于正确、高效地使用 EventBus 至关重要。务必遵循注册/注销的生命周期管理,合理选择 ThreadMode,并在大型项目中使用索引加速以获得最佳性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/91406.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/91406.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

初等数论简明教程

初等数论简明教程 本文给出初等数论中的一些重要的定理与例题&#xff0c;证明风格采用 整除线法 与 命题节点法。 整除线法 指推理的第 nnn 步左边的字符可由前面左边的字符得到&#xff0c;右边的字符可由前面右边的字符得到&#xff0c;整除线变成了推理线&#xff0c;既少…

Spring之核心容器(IoC,DI,基本操作)详解

Spring之核心容器IoC/DI/基本操作详解一、核心概念&#xff1a;IoC与DI的本质1.1 IoC&#xff08;Inversion of Control&#xff0c;控制反转&#xff09;传统开发模式&#xff08;无IoC&#xff09;IoC模式&#xff08;Spring容器管理&#xff09;1.2 DI&#xff08;Dependenc…

【论文阅读】基于注意力机制的冥想脑电分类识别研究(2025)

基于注意力机制的冥想脑电分类识别研究&#x1f4a1; Meta DataTitle基于注意力机制的冥想脑电分类识别研究Authors周梓涵Pub. date2025&#x1f4dc; Research Background & Objective背景&#xff1a; 现代生活压力导致心理问题日益突出&#xff0c;冥想作为一种有效的心…

GitHub 上 Star 数量前 8 的开源 Web 应用项目

原文链接&#xff1a;https://www.nocobase.com/cn/blog/github-open-source-web-applications。 近期&#xff0c;我们发布了多篇「Top GitHub Star 开源项目推荐」系列文章&#xff0c;受到了大量点赞与收藏&#xff0c;很多开发者留言表示希望能看到更多不同领域的开源工具推…

FATFS文件系统原理及其移植详解

一、FATFS简介 FATFS 是一个完全免费开源的 FAT/exFAT 文件系统模块&#xff0c;专门为小型的嵌入式系统而设计。它完全用标准 C 语言&#xff08;ANSI C C89&#xff09;编写&#xff0c;所以具有良好的硬件平台独立性&#xff0c;只需做简单的修改就可以移植到 8051、PIC、A…

KubeRay 和 Ray

KubeRay 和 Ray 不是替代关系&#xff0c;而是互补的协作关系。两者在分布式计算生态中扮演不同角色&#xff0c;共同构成完整的云原生 AI 解决方案。以下是具体分析&#xff1a;&#x1f527; 1. 核心定位差异Ray 是分布式计算引擎&#xff0c;提供底层 API&#xff08;如 ray…

破解轮胎仓储高密度与柔性管理难题

轮胎作为特殊的大件异形工业品&#xff0c;其仓储管理长期面临多重挑战&#xff1a;规格型号繁杂导致SKU数量庞大&#xff0c;重型载重对货架承重提出极高要求&#xff0c;橡胶材质对防压变形、避光防老化等存储环境存在严苛标准。传统平置堆垛或普通货架方案不仅空间利用率不足…

EVA series系列(上)

目录 一、EVA 1、概述 2、方法 二、EVA-02 1、概述 2、架构 三、EVA-CLIP 1、概述 2、方法 四、EMU 1、概述 2、架构 3、训练细节 4、评估 一、EVA 1、概述 为探寻大规模表征学习任务的MIM预训练任务在ViT基础上扩展到1B参数量规模&#xff0c;结合10M级别&am…

ABP VNext + EF Core 二级缓存:提升查询性能

ABP VNext EF Core 二级缓存&#xff1a;提升查询性能 &#x1f680; &#x1f4da; 目录ABP VNext EF Core 二级缓存&#xff1a;提升查询性能 &#x1f680;引言 &#x1f680;一、环境与依赖 &#x1f6e0;️二、集成步骤 ⚙️2.1 安装 NuGet 包2.2 注册缓存服务与拦截器2…

3.1k star!推荐一款开源基于AI实现的浏览器自动化插件工具 !

大家好&#xff01;今天&#xff0c;我要给大家介绍一款超实用的开源工具——Chrome MCP Server&#xff01;这款工具不仅能大幅提升我们的工作效率&#xff0c;还能让AI助手&#xff08;如Claude&#xff09;直接操控浏览器&#xff0c;实现自动化操作、内容分析等强大功能。 …

关于 OpenAI 的反思

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Python爬虫库性能与选型对比

Python常用爬虫库的优势对比。这是一个非常实用的问题&#xff0c;很多Python开发者都会面临选择合适爬虫工具的困惑。我根据网络很多搜索结果&#xff0c;整理出这些信息&#xff0c;为用户提供一个全面且清晰的对比分析。以下是Python中常用爬虫库的核心优势对比及选型建议&a…

NAT作业

拓扑图 实验要求 1.按照图示配置IP地址&#xff0c;公网地址100.1.1.1/24..较网“说过?,使“掩入到互联网&#xff0c;私服究的不到公的&#xff0c;使阳接入无三。.私网A通过NAPT&#xff0c;使R1接入到互联网&#xff0c;私网B通过EASY,IP&#xff0c;使R3接入到互联网实验思…

JAVA进阶--JVM

一.JVM的概述java语言有跨平台特点, 写一次java程序,可以在不同的平台上运行.(JVM虚拟机的作用)前提条件: 在不同的平台上安装不同的虚拟机(虚拟机就是一个翻译).java--->.class--->不同的虚拟机--->机器码1.jvm作用:负责将字节码翻译为机器码, 管理运行时内存2.jvm的…

基于Alpine构建MySQL镜像

文章目录基于Alpine构建MySQL镜像一、基础镜像选择与初始化1. 基础镜像选型2. 系统初始化二、核心配置构建1. 目录与权限配置2. 配置文件优化三、安全增强配置1. 密码策略强化2. 非root运行四、数据持久化与启动配置1. 数据卷声明2. 入口脚本优化五、完整Dockerfile示例六、关键…

Alamofire 网络请求全流解析,通俗易懂

Alamofire 网络请求全流程解析&#xff1a;从发起请求到处理响应 一、请求发起阶段&#xff1a;准备你的"快递" 1. 你告诉Alamofire要发什么"快递" // 就像告诉快递员&#xff1a;"我要寄一个包裹给https://api.example.com" AF.request("h…

链路聚合技术

链路聚合技术 链路聚合概述及应用场景 概述 链路聚合是把多条物理链路聚合在一起&#xff0c;形成一条逻辑链路。应用在交换机、路由器、服务器间链路&#xff0c;注意了&#xff0c;主机上面不能用链路聚合技术分为三层链路聚合和二层链路聚合链路聚合的作用 增加链路带宽提供…

SpringCloud之Zuul

SpringCloud之Zuul 推荐参考&#xff1a;https://www.springcloud.cc/spring-cloud-dalston.html#_router_and_filter_zuul 1. 什么是Zuul Spring Cloud Zuul 是 Netflix 提供的微服务网关核心组件&#xff0c;作为统一的 API 入口&#xff0c;承担请求路由、过滤、安全控制等…

低精度定时器 (timer_list) 和 高精度定时器 (hrtimer)

Linux 内核提供了两种主要类型的定时器&#xff0c;以满足不同的时间精度需求&#xff1a;低精度定时器 (timer_list) 和 高精度定时器 (hrtimer)。它们各有特点和适用场景。下面&#xff0c;我将分别提供它们在内核代码中的简化使用示例。1. 低精度定时器 (timer_list) 示例ti…

虚拟机VMware的使用方法

虚拟机VMware的使用方法VMware是全球领先的虚拟化技术提供商&#xff0c;其产品&#xff08;如VMware Workstation Pro&#xff09;允许用户在单一物理机上运行多个操作系统&#xff08;OS&#xff09;&#xff0c;实现资源高效利用、隔离测试和灵活部署。本文将详细介绍VMware…