今天是2025/03/26 17:01 day 12
总路线请移步主页Java大纲相关文章
今天进行JUC 1,2 个模块的归纳
首先是JUC的相关内容概括的思维导图
由于内容比较多且重要,
个人还整理了一份详细JUC的思维导图,需要的请评论。是 xmind文件
JUC 即 Java util concurrent,关于Java并发的核心概念和使用
一、基础组件
1. 线程管理
核心类与功能
-
ThreadFactory
-
作用:自定义线程的创建过程(如命名线程、设置优先级、守护线程标记)。
-
场景:
-
在日志系统中为线程命名(如
logger-thread-{n}
),便于问题排查。 -
统一管理线程的异常处理或资源分配。
-
-
示例:
ThreadFactory factory = r -> { Thread t = new Thread(r); t.setName("custom-thread-" + t.getId()); t.setPriority(Thread.NORM_PRIORITY); return t; }; ExecutorService executor = Executors.newFixedThreadPool(5, factory);
-
-
UncaughtExceptionHandler
-
作用:捕获线程运行时未被处理的异常,防止线程因异常终止。
-
场景:
-
全局异常监控(如记录崩溃日志并触发告警)。
-
优雅处理线程池任务中的未捕获异常。
-
-
示例:
Thread.setDefaultUncaughtExceptionHandler((t, e) -> { System.err.println("线程 " + t.getName() + " 崩溃: " + e.getMessage()); });
-
2. 原子类(Atomic)
核心类与原理
-
基础类型
-
AtomicInteger
/AtomicLong
:-
原理:基于 CAS(Compare-And-Swap)实现原子增减操作。
-
方法:
incrementAndGet()
,compareAndSet(expected, newValue)
。 -
场景:计数器(如统计接口调用次数)。
AtomicInteger counter = new AtomicInteger(0); counter.incrementAndGet(); // 线程安全的递增
-
-
AtomicBoolean
:-
场景:原子更新状态标志(如开关控制)。
AtomicBoolean isRunning = new AtomicBoolean(true); if (isRunning.compareAndSet(true, false)) { // 原子关闭 // 执行关闭逻辑 }
-
-
-
引用类型
-
AtomicReference
:-
场景:原子更新对象引用(如无锁单例模式)。
AtomicReference<Singleton> instance = new AtomicReference<>(); instance.compareAndSet(null, new Singleton()); // 线程安全初始化
-
-
AtomicStampedReference
:-
原理:通过版本戳(stamp)解决 ABA 问题(如并发队列中的节点更新)。
-
方法:
compareAndSet(expectedRef, newRef, expectedStamp, newStamp)
。
-
-
-
高性能累加器
-
LongAdder
:-
优势:在高并发场景下,性能优于
AtomicLong
(内部使用分段计数减少竞争)。 -
场景:统计 QPS(每秒请求数)等高频计数器。
LongAdder adder = new LongAdder(); adder.increment(); // 线程安全的累加
-
-
二、并发工具
1. 并发集合
核心类与设计
-
ConcurrentHashMap
-
JDK 7 vs JDK 8:
-
JDK7:分段锁(Segment),每段独立加锁。
-
JDK8+:Node + CAS + synchronized(锁粒度更细,性能更高)。
-
-
场景:高并发缓存、全局配置存储。
-
方法:
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>(); map.putIfAbsent("key", "value"); // 原子插入
-
-
CopyOnWriteArrayList
-
原理:写操作时复制新数组(读无锁,写加锁)。
-
场景:读多写少的监听器列表(如事件监听器集合)。
-
缺点:写操作性能差(适合低频修改)。
-
-
阻塞队列(BlockingQueue)
-
ArrayBlockingQueue
:-
特点:固定容量,基于数组实现。
-
场景:生产者-消费者模型(如任务缓冲队列)。
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(100); queue.put(1); // 阻塞插入(队列满时等待) Integer value = queue.take(); // 阻塞获取(队列空时等待)
-
-
LinkedBlockingQueue
:-
特点:可选容量(默认无界),基于链表实现,吞吐量更高。
-
风险:无界队列可能导致内存溢出。
-
-
DelayQueue
:-
要求:元素需实现
Delayed
接口,指定延迟时间。 -
场景:定时任务调度(如订单超时取消)。
-
-
2. 同步器(Synchronizers)
核心类与使用
-
CountDownLatch
-
作用:等待一组线程完成任务后触发后续逻辑(一次性)。
-
场景:
-
服务启动依赖(等待所有子模块初始化完成)。
-
并行计算后汇总结果。
-
-
示例:
CountDownLatch latch = new CountDownLatch(3); // 线程1/2/3 执行任务后调用 latch.countDown() latch.await(); // 主线程阻塞,直到计数器归零
-
-
CyclicBarrier
-
作用:多线程到达屏障后触发回调,支持重复使用。
-
场景:多阶段任务协作(如并行计算分阶段汇总)。
-
示例:
CyclicBarrier barrier = new CyclicBarrier(3, () -> { System.out.println("所有线程到达屏障!"); }); // 线程调用 barrier.await() 等待其他线程
-
-
Semaphore
-
作用:控制并发资源访问数(如限流)。
-
场景:
-
数据库连接池管理。
-
接口 QPS 限制。
-
-
示例:
Semaphore semaphore = new Semaphore(10); // 允许10个并发 semaphore.acquire(); // 获取许可(无可用许可时阻塞) try { // 访问资源 } finally { semaphore.release(); }
-
-
Exchanger
-
作用:两个线程间交换数据(双向传输)。
-
场景:
-
双缓冲数据交换(如生产者-消费者交替处理缓冲区)。
-
游戏服务器中玩家数据同步。
-
-
示例:
Exchanger<String> exchanger = new Exchanger<>(); // 线程A: String dataA = exchanger.exchange("Data from A"); // 阻塞等待交换 // 线程B: String dataB = exchanger.exchange("Data from B");
-
对比与选型指南
工具 | 特点 | 适用场景 |
---|---|---|
CountDownLatch | 一次性,等待外部事件完成 | 服务启动依赖、并行计算汇总 |
CyclicBarrier | 可重复使用,等待内部线程同步 | 分阶段任务协作 |
Semaphore | 控制并发数,支持公平/非公平模式 | 资源池管理、接口限流 |
Exchanger | 线程间双向数据交换 | 双缓冲切换、数据同步 |