JavaGuide自学记录2–Java集合源码+一些特殊类
CopyOnWriteArrayList
JDK1.5 引入了 Java.util.concurrent(JUC)包,其中唯一的线程安全 List 实现就是 CopyOnWriteArrayList 。
CopyOnWriteArrayList 线程安全的核心在于其采用了 写时复制(Copy-On-Write) 的策略,从 CopyOnWriteArrayList 的名字就能看出了。
当需要修改( add,set、remove 等操作) CopyOnWriteArrayList 的内容时,不会直接修改原数组,而是会先创建底层数组的副本,对副本数组进行修改,修改完之后再将修改后的数组赋值回去,这样就可以保证写操作不会影响读操作了。
只有写写会互斥,则读写不互斥,会有一些数据不一致问题。
阻塞队列和非阻塞队列
Java 提供的线程安全的 Queue 可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是 BlockingQueue,非阻塞队列的典型例子是 ConcurrentLinkedQueue,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列。 阻塞队列可以通过加锁来实现,非阻塞队列可以通过 CAS 操作实现
当然ArrayBlockingQueue也能做非阻塞
AtomicInteger 线程安全原理简单分析
AtomicInteger类的部分源码:
// setup to use Unsafe.compareAndSwapInt for updates(更新操作时提供“比较并替换”的作用)
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
private volatile int value;
AtomicInteger 类主要利用 CAS (compare and swap) + volatile 和 native 方法来保证原子操作,从而避免synchronized 的高开销,执行效率大为提升。
CAS 的原理是拿期望的值和原本的一个值作比较,如果相同则更新成新的值。UnSafe 类的 objectFieldOffset() 方法是一个本地方法,这个方法是用来拿到“原来的值”的内存地址。另外 value 是一个 volatile 变量,在内存中可见,因此 JVM 可以保证任何时刻任何线程总能拿到该变量的最新值。
异步编排 CompletableFuture
Java里面的
京东的 asyncTool 这个并发框架,里面大量使用到了 CompletableFuture
从 RocketMQ 4.7 开始,RocketMQ 引入了 CompletableFuture来实现异步消息处理 。
其他JavaGuide的集合类
LinkedHashMap可以实现LRU算法
DelayQueue 底层是使用优先队列 PriorityQueue 来存储元素,为了保证线程安全使用了ReentrantLock,
DelayQueue 通常用于实现定时任务调度和缓存过期删除等场景。