新闻中心

J*a里如何实现线程安全的事件发布与订阅_事件发布订阅线程安全操作说明

2025-12-05
浏览次数:
返回列表
使用CopyOnWriteArrayList可实现线程安全的事件发布订阅,适合读多写少场景;通过读写锁+列表快照可提升高并发性能,结合线程池支持异步分发,确保事件处理不阻塞发布线程,根据场景选择方案。

java里如何实现线程安全的事件发布与订阅_事件发布订阅线程安全操作说明

在J*a中实现线程安全的事件发布与订阅,关键在于确保多个线程同时注册、注销或触发事件时不会引发并发问题。常见的做法是使用线程安全的数据结构来管理监听器列表,并保证事件发布过程中的读写一致性。

使用CopyOnWriteArrayList管理监听器

最简单且高效的线程安全方式是使用CopyOnWriteArrayList存储订阅者(监听器)。该集合在修改时会复制底层数组,适合读多写少的场景,如事件广播。

示例代码:

import j*a.util.concurrent.CopyOnWriteArrayList;

public class EventBus {
    private final CopyOnWriteArrayList<EventListener> listeners = new CopyOnWriteArrayList<>();

    public void subscribe(EventListener listener) {
        listeners.add(listener);
    }

    public void unsubscribe(EventListener listener) {
        listeners.remove(listener);
    }

    public void publish(Event event) {
        for (EventListener listener : listeners) {
            listener.onEvent(event);
        }
    }
}

interface EventListener {
    void onEvent(Event event);
}

class Event {
    private final String data;

    public Event(String data) {
        this.data = data;
    }

    public String getData() {
        return data;
    }
}

说明:CopyOnWriteArrayList在遍历过程中允许添加/删除操作,不会抛出ConcurrentModificationException,非常适合事件通知这种频繁读取、较少变更的场景。

使用显式同步控制(适用于复杂逻辑)

如果需要更细粒度的控制,比如支持按类型订阅、异步分发等,可以使用synchronizedReentrantReadWriteLock保护监听器集合。

示例:使用读写锁提升性能

Writer Writer

企业级AI内容创作工具

Writer 220 查看详情 Writer
import j*a.util.ArrayList;
import j*a.util.List;
import j*a.util.concurrent.locks.ReadWriteLock;
import j*a.util.concurrent.locks.ReentrantReadWriteLock;

public class ThreadSafeEventBus {
    private final List<EventListener> listeners = new ArrayList<>();
    private final ReadWriteLock lock = new ReentrantReadWriteLock();

    public void subscribe(EventListener listener) {
        lock.writeLock().lock();
        try {
            listeners.add(listener);
        } finally {
            lock.writeLock().unlock();
        }
    }

    public void unsubscribe(EventListener listener) {
        lock.writeLock().lock();
        try {
            listeners.remove(listener);
        } finally {
            lock.writeLock().unlock();
        }
    }

    public void publish(Event event) {
        lock.readLock().lock();
        try {
            // 创建快照避免持有锁期间调用回调
            List<EventListener> safeListeners = new ArrayList<>(listeners);
            for (EventListener listener : safeListeners) {
                listener.onEvent(event);
            }
        } finally {
            lock.readLock().unlock();
        }
    }
}

优势:读操作不阻塞,适合高频率事件发布;通过拷贝监听器列表,避免在锁内执行可能耗时的回调方法。

异步事件分发与线程池集成

若事件处理较耗时,建议将事件分发交给线程池,避免阻塞发布线程。

改进publish方法:

private final ExecutorService executor = Executors.newFixedThreadPool(4);

public void publish(Event event) {
    lock.readLock().lock();
    List<EventListener> safeListeners;
    try {
        safeListeners = new ArrayList<>(listeners);
    } finally {
        lock.readLock().unlock();
    }

    for (EventListener listener : safeListeners) {
        executor.submit(() -> listener.onEvent(event));
    }
}

注意:异步模式下事件顺序不保证,需根据业务决定是否使用单线程线程池(如newSingleThreadExecutor)来保序。

基本上就这些。选择哪种方式取决于你的使用场景:轻量级用CopyOnWriteArrayList,功能复杂可配合读写锁和线程池,关键是保证监听器列表的线程安全和事件发布的稳定性。

以上就是J*a里如何实现线程安全的事件发布与订阅_事件发布订阅线程安全操作说明的详细内容,更多请关注其它相关文章!


# 遍历  # seo定制培训  # 潢川企业号推广营销费用  # 晴隆抖音seo咨询  # 网站建设优化案例  # 无锡网站建设网站运营  # 湘潭网站建设管理论文  # 河北网站建设官网  # 大余关键词优化排名  # 合肥网站建设公司哪家好  # 成都seo排名费用  # 适用于  # java  # 多个  # 多写  # 过程中  # 时长  # 回调  # 如何实现  # 好了  # 数据结构  # 有锁  # 线程安全 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 抓大鹅无需下载版 抓大鹅秒玩版入口  CSS Flexbox与媒体查询:实现响应式布局中元素的并排与堆叠  C++如何连接MySQL数据库_C++使用Connector/C++操作MySQL数据库教程  Spring Boot嵌入式服务器与J*a EE:功能支持深度解析  Python自定义类排序:解决lambda键值访问TypeError的实践指南  windows10怎么关闭系统提示音_windows10彻底静音设置方法  Surface怎么安装系统 微软Surface Pro U盘重装win11教程  微博网页版首页入口 微博电脑端官网登录链接  SteamMachine定价或为699美元 大家想入手吗?  将HTML Canvas内容转换为可上传的图像文件(File对象)  J*a TimerTask中HashMap意外清空的深层原因与解决方案  Flexbox布局实践:实现粘性导航栏与底部固定页脚  J*aScript:在map操作中高效处理空数组  Python vgamepad库按键模拟:正确使用XUSB_BUTTON常量  Windows7怎么硬盘安装 Windows7提取ISO镜像到非系统盘并运行setup.exe实现硬盘直装【教程】  HTML长属性值处理:表单action路径优化与代码规范应对  中兴Axon42Ultra怎样在文件App筛图_iPhone中兴Axon42Ultra文件App筛图【图片筛选】  凉拌黄瓜怎么拌更入味 凉拌黄瓜简单家常做法  mysql备份恢复性能优化_mysql备份恢复性能优化方法  在J*a中如何隐藏复杂性_使用门面模式组织对象交互  TikTok评论显示延迟如何处理 TikTok评论刷新优化方法  离线运行Go语言之旅:本地部署与GOPATH配置指南  拷贝漫画电脑版官网入口 拷贝漫画(PC版)在线直达  Node.js CSV 数据处理:基于字段值条件过滤整条记录的策略  在J*a中如何使用Stream.map转换元素_Stream映射操作解析  腾讯QQ邮箱官方网站_QQ邮箱网页版在线登录  俄罗斯搜索引擎Yandex指南 附2025年免登录官网入口  win11开机启动修复循环怎么办 Win11无法进入系统高级启动解决方法【修复】  淘宝支付提示失败如何解决 淘宝支付流程优化方法  Promise错误处理:在catch后终止链式then执行的策略  基于动态规划的房屋花卉种植最小成本算法详解  win11 arm版怎么安装 M1/M2 Mac虚拟机安装ARM win11的方法  c++中的std::basic_string的SSO优化_c++短字符串优化深度解析  深入理解Promise链:如何在catch后中断then的执行  vivo浏览器自带的下载器速度慢怎么办 vivo浏览器提升文件下载速度的技巧  京东单号查询入口_京东快递订单追踪入口  邮政快递单号查询入口 邮政快递物流信息在线查询入口  J*a应用程序首次运行自动创建文件与目录的最佳实践  随机参数递归函数的基准调用次数与时间复杂度探究  Spyder启动失败:字体文件权限拒绝错误解决方案  如何在CSS中使用visited与link控制链接颜色_visited link伪类配合  在FastAPI中利用lifespan与依赖注入高效管理Redis连接池  windows10怎么查看本机ip_windows10命令提示符ipconfig使用  C++如何使用AddressSanitizer(ASan)_C++调试工具中检测内存访问错误的利器  Win11蓝牙耳机断连怎么解决 Win11蓝牙设置重新配对与驱动更新【技巧】  怎样把文件彻底粉碎无法恢复_Windows下安全删除敏感数据【隐私保护】  12306几点到几点不能订票? | 官方最新系统维护时间全解析  Python Socket多播通信中指定源IP地址的实践指南  《铁拳8》黑皮辣妹新实机:元气满满的18岁少女!  海棠电脑版入口_通过电脑访问海棠官网阅读 

搜索