ArrayList线程安全解决方案

本文深入解析Android中的Handler机制,包括消息传递原理、关键类的作用及其内部运作方式。并通过示例代码展示如何在实际项目中使用Handler进行线程间通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ArrayList本身是线程不安全的容器,除了使用synchronized关键字外,还有多种方式可以保证其线程安全性。以下是完整的解决方案:

一、Collections工具类包装

List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>());

原理

  • 返回SynchronizedRandomAccessList内部类

  • 所有方法都使用同步代码块锁定mutex对象

  • 迭代时需要手动同步

使用示例

// 写入时自动同步
synchronizedList.add("item");

// 遍历时需要手动同步
synchronized(synchronizedList) {
    for (String item : synchronizedList) {
        // 操作item
    }
}

二、CopyOnWriteArrayList

CopyOnWriteArrayList<String> copyOnWriteList = new CopyOnWriteArrayList<>();

核心机制

  1. 写时复制:修改操作(add/set/remove)时复制整个底层数组

  2. 读无锁:读操作基于不可变数组,无需同步

  3. 最终一致性:读操作可能读到旧数据

适用场景

  • 读多写少(如监听器列表、配置信息)

  • 遍历操作远多于修改操作

性能特点

操作时间复杂度锁机制
读(get)O(1)无锁
写(add)O(n)ReentrantLock

三、ThreadLocal隔离

ThreadLocal<List<String>> threadLocalList = ThreadLocal.withInitial(ArrayList::new);

实现原理

  • 每个线程持有独立的ArrayList实例

  • 完全避免多线程竞争

  • 需要自行处理线程间的数据传递

适用场景

  • 线程封闭场景

  • 方法调用链中的临时列表

  • 不需要跨线程共享数据的情况

四、不可变集合

List<String> immutableList = List.of("a", "b", "c");
// 或
List<String> immutableList = Collections.unmodifiableList(new ArrayList<>());
  • 完全禁止修改操作(add/set/remove抛出UnsupportedOperationException)

  • 最安全的线程保障

  • 适用于配置信息等不变数据集

五、并发队列替代方案

// 有界队列
ArrayBlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(100);

// 无界队列
ConcurrentLinkedQueue<String> concurrentQueue = new ConcurrentLinkedQueue<>();

适用场景

  • 生产者-消费者模式

  • 需要阻塞/非阻塞操作

  • 替代List作为临时缓冲区

六、性能对比

方案读性能写性能内存开销适用场景
Collections.synchronizedList通用方案
CopyOnWriteArrayList读多写少
ThreadLocal线程封闭
不可变集合不支持静态数据
并发队列生产者-消费者模式

七、最佳实践建议

  1. 读多写少:优先考虑CopyOnWriteArrayList

    // 事件监听器列表
    private final CopyOnWriteArrayList<EventListener> listeners = new CopyOnWriteArrayList<>();
  2. 写多读少:使用Collections.synchronizedList+批量操作

    List<String> syncList = Collections.synchronizedList(new ArrayList<>());
    
    // 批量添加时只同步一次
    synchronized(syncList) {
        syncList.addAll(batchData);
    }
  3. 超高并发:考虑分段锁方案(类似ConcurrentHashMap)

    class SegmentList<T> {
        private final List<T>[] segments;
        private final Object[] locks;
        
        public SegmentList(int segmentCount) {
            // 初始化分段
        }
        
        public void add(T item) {
            int segment = hash(item) % segments.length;
            synchronized(locks[segment]) {
                segments[segment].add(item);
            }
        }
    }
  4. Java 9+优化:使用List.of()创建不可变集合

    private static final List<String> CONSTANT_LIST = List.of("A", "B", "C");

八、常见误区

  1. 错误认为volatile能保证线程安全

    // 错误示例!volatile只能保证引用可见性,不能保证集合操作原子性
    private volatile ArrayList<String> list = new ArrayList<>();
  2. 忽略复合操作的原子性

    // 错误!contains+add不是原子操作
    if (!list.contains(item)) {
        list.add(item);
    }
  3. 过度同步导致性能问题

    // 不必要的方法级同步
    public synchronized void addAll(List<String> items) {
        list.addAll(items);
    }

选择线程安全方案时,需要根据实际场景的读写比例、性能要求和一致性需求做出权衡。对于大多数应用场景,CopyOnWriteArrayListCollections.synchronizedList()是最常用的解决方案。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值