Immutability 模式:如何利用不变性解决并发问题?
不变性(Immutability)模式:对象一旦创建后状态不再变化。解决并发问题最简单的方法——让共享变量只有读操作。
快速实现具备不可变性的类
- 类和属性都是
final的,所有方法均是只读的 String、Long、Integer、Double等包装类均严格遵守此规则String.replace()不修改原value[],而是返回新字符串
不变性(Immutability)模式:对象一旦创建后状态不再变化。解决并发问题最简单的方法——让共享变量只有读操作。
final 的,所有方法均是只读的String、Long、Integer、Double 等包装类均严格遵守此规则String.replace() 不修改原 value[],而是返回新字符串Guava RateLimiter:Google 开源的限流工具类,基于令牌桶算法实现。
//限流器流速:2 个请求/秒
RateLimiter limiter = RateLimiter.create(2.0);
//执行任务的线程池
ExecutorService es = Executors.newFixedThreadPool(1);
//记录上一次执行时间
prev = System.nanoTime();
//测试执行 20 次
for (int i = 0; i < 20; i++) {
//限流器限流
limiter.acquire();
//提交任务异步执行
es.execute(() -> {
long cur = System.nanoTime();
//打印时间间隔:毫秒
System.out.println((cur - prev) / 1000_000);
prev = cur;
});
}
// 输出结果:
// ...
// 500
// 499
// 500
// 499

并发编程可以总结为三个核心问题:分工、同步、互斥。
已有 synchronized,还需要 Lock 的原因——需要锁支持以下能力以破坏不可抢占条件:
🎯 目标等级:L2 | ⏱ 建议用时:5 min | 🏷 标签:线程池 / 核心价值
线程池的核心价值是复用线程,避免频繁创建/销毁的开销。三大好处:降低资源消耗、提高响应速度、让线程可统一分配、调优和监控。
🎯 目标等级:L2-L3 | ⏱ 建议用时:10 min | 🏷 标签:锁 / 锁分类
Java 锁按七大维度划分:公平性、获取方式、可重入性、共享性、阻塞方式、优化策略、实现方式。选型看三点:竞争强度、任务时长、读写比例,没有最好的锁,只有最适合场景的锁。
Java 内存模型(Java Memory Model),简称 JMM。Java 内存模型的目标是为了解决由可见性和有序性导致的并发安全问题。Java 内存模型通过 屏蔽各种硬件和操作系统的内存访问差异,以实现让 Java 程序在各种平台下都能达到一致的内存访问效果。
物理机遇到的并发问题与虚拟机中的情况有不少相似之处,物理机对并发的处理方案对于虚拟机的实现也有相当大的参考意义。
技术在进步,CPU、内存、I/O 设备的性能也在不断提高。但是,始终存在一个核心矛盾:CPU、内存、I/O 设备存在很大的速度差异 - CPU 远快于内存,内存远快于 I/O 设备。木桶短板理论告诉我们:一只木桶能装多少水,取决于最短的那块木板。同理,程序整体性能取决于最慢的操作(即 I/O 操作),所以单方面提高 CPU、内存的性能是无效的。
Java 并发编程中,分工工具是处理复杂并行任务的核心利器。当单个任务过于庞大或具有复杂的依赖关系时,我们需要将其拆分为多个子任务并行执行,最后汇总结果。Java 提供了多种分工工具来应对不同场景:ForkJoinPool 面向分治递归任务,CompletableFuture 面向异步编排与聚合,CompletionService 面向批量并行任务的结果收集。
对于简单的并行任务,你可以通过"线程池 + Future"的方案来解决;如果任务之间有聚合关系,无论是 AND 聚合还是 OR 聚合,都可以通过 CompletableFuture 来解决;而批量的并行任务,则可以通过 CompletionService 来解决。
【Java 并发】专题系统梳理多线程并发编程的核心知识体系,涵盖 Java 内存模型(JMM)、线程生命周期与同步机制、锁机制(synchronized/ReentrantLock/AQS)、无锁并发(CAS/原子类/ThreadLocal)等核心主题。同时深入线程池原理、并发容器、同步与分工工具类等实战内容,帮助理解并发编程的本质问题与解决方案。
原子性、可见性、有序性、死锁、上下文切换JMM、Happens-Before、volatile、synchronized、锁升级Thread、Runnable、Callable、线程生命周期、interruptReentrantLock、AQS、CAS、悲观锁、乐观锁CAS、原子类、ThreadLocal、ABA 问题、Copy-on-WriteAQS、CLH 队列、独占锁、共享锁、ConditionConcurrentHashMap、CopyOnWriteArrayList、BlockingQueue、分段锁、CASThreadPoolExecutor、corePoolSize、拒绝策略、workQueue、ExecutorsCountDownLatch、Semaphore、CyclicBarrier、信号量、AQSCompletableFuture、ForkJoinPool、FutureTask、工作窃取、异步编排🎯 目标等级:L2 | ⏱ 建议用时:5 min | 🏷 标签:并发简介 / 基础概念
二者最关键的区别在于是否同时发生:并发是多个任务在同一时间段内交替执行(逻辑上的同时),并行是多个任务在多核上真正同时执行(物理上的同时)。并发是执行模型,并行是硬件能力。