当前位置: 首页 > news >正文

java-JUC概述(进行分类总结-包含原子类、并发集合、线程等)

 文章目录

目录

 文章目录

前言

一、原子类(Atomic Classes)

1. 基本类型原子类

2. 引用类型原子类

3. 数组原子类

4. 字段更新器

5.问题

1.其他基本类型为什么不在原子类中

​​1.CAS指令的底层支持​​

2.高频使用场景优先​​

3.替代方案与扩展能力

二、并发集合(Concurrent Collections)

1.ConcurrentHashMap

2.CopyOnWriteArrayList

3.BlockingQueue 接口 

三、锁

1.Lock 接口

2.ReadWriteLock 接口

3.Condition 接口

 4.AbstractQueuedSynchronizer (AQS)

四、同步工具类(Synchronizers)

1.CountDownLatch

2.Semaphore

3.CyclicBarrier

4.Exchanger

5.Phaser(Java 7+)

总结

五、线程池 

1.Executor 接口

2.ExecutorService 接口(extends Executor)

3.Executors 工厂类

六、异步结果(Future)

1.Future 接口

2.CompletableFuture(JDK1.8)

 七、分治框架(Fork/Join)

1.ForkJoinPool 

2.RecursiveTask(返回结果) / RecursiveAction(无结果)

 总结



前言

java.util.concurrent(JUC)包是 Java 并发编程的核心工具包,提供了丰富的多线程编程工具类、接口和框架

下面从该包下常用的类和接口进行总结


一、原子类(Atomic Classes)

Java原子类(Atomic Classes)是java.util.concurrent.atomic包中提供的一组工具类,用于在多线程环境下实现​无锁的线程安全操作​。其核心机制基于​CAS(Compare-And-Swap)​硬件指令,通过硬件级原子操作保证变量修改的不可分割性
适用于计数器、状态标志等简单原子操作场景。

为什么需要原子类:

在线程中使用普通的Integer、Long也是可以的,只有我们进行复合操作(i++、i=i+1)这样的是线程不安全的,其他安全情况是可以使用普通基本类型的,也就是说原子类已经帮我们优化了i++(getAndIncrement)、i++(compareAndSet)

不使用原子类可以吗?--可以

那么就需要自行加锁(lock/synchronized ),这样的话开销就大了,或者手动实现CAS

1. 基本类型原子类

  • AtomicInteger / AtomicLong / AtomicBoolean

  • 作用:提供原子操作的整型、长整型和布尔值。

  • 核心方法incrementAndGet()compareAndSet()

AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet(); // 原子自增
count.compareAndSet(0, 1); // CAS 更新

2. 引用类型原子类

  • AtomicReference / AtomicStampedReference(解决 ABA 问题)

  • 作用:原子更新对象引用。

AtomicReference<String> ref = new AtomicReference<>("init");
ref.compareAndSet("init", "new"); // CAS 更新引用

3. 数组原子类

  • AtomicIntegerArray / AtomicLongArray / AtomicReferenceArray

  • 作用:原子更新数组中的元素。

int[] arr = {1, 2, 3};
AtomicIntegerArray atomicArray = new AtomicIntegerArray(arr);
atomicArray.getAndIncrement(0); // 原子更新索引0处的值

4. 字段更新器

  • AtomicIntegerFieldUpdater / AtomicLongFieldUpdater / AtomicReferenceFieldUpdater

  • 作用:原子更新对象的字段(需 volatile 修饰)。

5.问题

1.其他基本类型为什么不在原子类中

这里大家发现了Integer,Long,Boolean这个基本类型都有原子类,为什么其他的没有呢

核心原则​​:原子类的设计以​​高频需求​​和​​硬件支持​​为导向,通过通用性设计(如AtomicReference)覆盖低频场景,避免冗余实现。对于未覆盖的类型,开发者可结合现有工具灵活扩展。

​1.CAS指令的底层支持​
  1. ​整数类型的天然适配​​:CAS(Compare-And-Swap)是硬件级别的原子操作,通常直接支持32位(int)和64位(long)整数的原子性操作。
  2. 浮点数的复杂性​​:double是64位浮点数,其位操作需考虑精度问题,且硬件对浮点数的CAS支持较弱(部分架构甚至不支持

2.高频使用场景优先​
  1. intlong是编程中最常用的数值类型(如计数器、ID生成),boolean用于标志位,需求覆盖率高。
  2. shortbyte等类型因使用场景较少(如特定协议解析),未被纳入核心原子类。
3.替代方案与扩展能力

对于非原生原子类型(如DoubleFloat),可通过AtomicReference包装对象引用实现原子性

AtomicReference<Double> atomicDouble = new AtomicReference<>(0.0);
atomicDouble.compareAndSet(0.0, 1.0); // 原子更新

二、并发集合(Concurrent Collections)

在多线程环境下,传统的集合类(如 ArrayListHashMap)是非线程安全的,可能导致数据不一致或并发修改异常。
并发集合提供线程安全的替代方案,通过优化锁机制(如分段锁、CAS)或数据拷贝策略,实现高并发下的高性能读写。
下面介绍常用的并发集合

1.ConcurrentHashMap

普通的HashMap我们都知道里面没加锁,可以想一下多个线程同时对一个实例对象进行插入同一个值的时候(put(k,v)),k一样,多个线程修改表中的位置是一样的,就可能出现最终值不一致

  • 作用:线程安全的哈希表,代替HashMap

  • 特点

    • Java 7:分段锁(Segment),降低锁粒度,允许多线程同时读写不同段。

    • Java 8+:使用 CAS + synchronized 锁单个桶(Node),进一步优化并发性能。

  • 适用场景:高并发读写,如缓存、计数器。

  • 示例

简单来说,锁的就是每个链表,对于不同的链表不用上锁,因为产生不了并发问题,没涉及修改用一个变量

2.CopyOnWriteArrayList

  • 作用:线程安全的 List,适用于读多写少的场景(如监听器列表)代替Arraylist/LinkedList
  • 原理:写操作时复制整个底层数组,读操作无锁。
  • 缺点:写操作性能差(每次复制数组)而且锁的都是整个代码块,数据量大时慎用。

3.BlockingQueue 接口 

  • 作用:支持阻塞操作的队列,用于生产者-消费者模型。

  • 常用实现类

    • ArrayBlockingQueue:基于数组的有界队列,容量固定。

    • LinkedBlockingQueue:基于链表的队列,默认无界(可设置容量)。

    • PriorityBlockingQueue:按优先级排序的无界队列

    • SynchronousQueue:不存储元素,插入操作必须等待移除操作。

三、锁

提供更灵活的锁机制和线程同步工具,比传统的 synchronized 关键字更加灵活,支持可中断锁、超时锁等高级功能。

1.Lock 接口

  • 实现类ReentrantLock

    • 特点:可重入锁,支持公平锁与非公平锁。

    • 核心方法

lock.lock();          // 获取锁
lock.tryLock(1, TimeUnit.SECONDS);  // 尝试获取锁(支持超时)
lock.unlock();        // 释放锁

2.ReadWriteLock 接口

  • 实现类ReentrantReadWriteLock

    • 特点:读写分离,允许多个读线程同时访问,写线程独占。

3.Condition 接口

  • 作用:替代 Object.wait()/notify(),与 Lock 配合实现线程间协作。

Condition condition = lock.newCondition();
condition.await();      // 等待
condition.signal();     // 唤醒

     4.AbstractQueuedSynchronizer (AQS)

    • 作用:构建锁和同步器的底层框架(如 ReentrantLockSemaphore 均基于 AQS)。

    • 核心机制:通过 state 变量和 CLH 队列管理线程的阻塞与唤醒。

    四、同步工具类(Synchronizers)

    协调多个线程的执行顺序或资源访问。

    1.CountDownLatch

    • 作用:一个或多个线程等待其他线程完成操作。

    • 示例

    CountDownLatch latch = new CountDownLatch(3);
    latch.countDown();  // 计数器减1
    latch.await();      // 等待计数器归零

    2.Semaphore

    作用:控制同时访问资源的线程数(信号量模型)。

    Semaphore semaphore = new Semaphore(5); // 允许5个线程同时访问
    semaphore.acquire();    // 获取许可
    semaphore.release();    // 释放许可

    3.CyclicBarrier

    • 作用:一组线程互相等待,达到屏障点后继续执行。

    • 特点:可重复使用。

    CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("所有线程完成阶段任务"));for (int i = 0; i < 3; i++) {new Thread(() -> {try {// 阶段 1processData();barrier.await();// 阶段 2analyzeData();barrier.await();} catch (Exception e) {e.printStackTrace();}}).start();
    }

    4.Exchanger

    作用:两个线程间交换数据。

    适用场景​​:两个线程间精确交换数据(如线程间传递计算结果)。线程A生成数据,线程B处理数据,双方通过Exchanger交换数据

    Exchanger<String> exchanger = new Exchanger<>();
    String data = exchanger.exchange("data1"); // 阻塞直到另一个线程调用exchange

    5.Phaser(Java 7+)

    • 作用:分阶段的多线程任务同步器,替代 CyclicBarrier 和 CountDownLatch

    • 适用场景​​:动态任务分片(如MapReduce任务)、多阶段并行计算。

    总结

    工具类​​核心机制​​线程关系​​可重用性​​典型场景​
    ​CountDownLatch​计数器减至0触发1:N(主线程等待子线程)等待多个任务完成
    ​CyclicBarrier​计数器加至N后触发并重置N:N(线程间相互等待)分阶段并行任务同步
    ​Semaphore​许可资源池管理共享资源竞争限流、资源池控制
    ​Phaser​动态阶段划分与同步动态参与线程动态任务分片与多阶段计算
    ​Exchanger​双线程数据交换点1:1数据交换线程间数据传递

    五、线程池 

    管理线程的生命周期,避免频繁创建和销毁线程的开销。

    1.Executor 接口

    核心方法execute(Runnable command)

    2.ExecutorService 接口(extends Executor)

    • 扩展功能:提交任务、关闭线程池、获取 Future 对象。

    • 实现类

      • ThreadPoolExecutor:可配置核心线程数、最大线程数、队列等参数。

      • ScheduledThreadPoolExecutor:支持定时和周期性任务。

    3.Executors 工厂类

    常用方法有5个: 

    • 基于ThreadPoolExecutor
      • newFixedThreadPool(int nThreads):固定大小线程池。
      • newCachedThreadPool():弹性线程池(无界,空闲线程自动回收)
      • ScheduledThreadPoolExecutor():创建单一线程池

    • 基于ScheduledThreadPoolExecutor

      • ScheduledThreadPool(int corePoolSize):定时任务
    • 基于ForkJoinPool(JDK1.7)

      • newWorkStealingPool(int parallelism):工作窃取线程池

        • 高吞吐量​​:适合CPU密集型任务,减少线程等待

        • ​​任务窃取机制​​:空闲线程从其他线程的队列尾部窃取任务。

    六、异步结果(Future)

    异步计算结果,支持任务结果的获取和取消。

    1.Future 接口

    核心方法

    future.get();     // 阻塞获取结果
    future.isDone();  // 检查任务是否完成

    2.CompletableFuture(JDK1.8)

    支持链式异步编程,组合多个异步任务。

    CompletableFuture.supplyAsync(() -> "Hello").thenApply(s -> s + " World").thenAccept(System.out::println);

     七、分治框架(Fork/Join)

    将大任务拆分为小任务并行执行,最后合并结果(类似 MapReduce)。适合分治问题

    1.ForkJoinPool 

    基于工作窃取算法(Work-Stealing),空闲线程从其他队列窃取任务。

    2.RecursiveTask(返回结果) / RecursiveAction(无结果)

    就如名字适用于递归,例如计算斐波那契(0, 1, 1, 2, 3, 5, 8, 13, 21, 34)

    class FibonacciTask extends RecursiveTask<Integer> {protected Integer compute() {if (n <= 1) return n;FibonacciTask f1 = new FibonacciTask(n - 1);f1.fork();FibonacciTask f2 = new FibonacciTask(n - 2);return f2.compute() + f1.join();}
    }

     总结

    首先确认一个事情JUC包核心目标是 简化并发编程的复杂度,多线程咱们一般使用手动创建线程,但是每次都要创建和销毁线程,导致高并发的时候浪费和消耗资源,因此JUC包提供了线程池,其中JUC包下的工具类,例如线程协作工具(CountDownLatch,Semaphore),原子类,异步任务等都适用于手动创建线程和线程池,而使用多线程的情况下会出现的线程安全问题,JUC包里面提供了锁(lock包)例如(ReentrantReadWriteLock、ReentrantLock)等,以及并发集合(ConcurrentHashMap )等能帮我们更灵活的解决线程安全问题,但是加锁是会占用资源的(其他线程要等待),因此有些简单情况我们可以使用CAS来代替锁,因此JUC包下的原子类(AtomicInteger)等能帮我们很好解决这个问题,当然我们也可以手动实现(底层就是CAS),解决了线程安全,那么对于多个线程的控制,同步等协调操作,JUC也给出了工具类(CountDownLatch、Exchanger、Phaser)等,但是还有是有个问题现在的线程都需要执行完之后才能获取结果,因此出现了异步任务,可以通过(Future)等接口来异步获取结果,而不用等待。因此现在线程资源,线程安全,线程协作,异步任务都有了实现。

    1.优先选择高层抽象:

    使用 ConcurrentHashMap 替代手动同步的 HashMap。

    使用 ExecutorService 管理线程,而非直接创建 Thread。

    2.合理选择同步工具:

    一次性等待用 CountDownLatch,循环等待用 CyclicBarrier。

    资源限流用 Semaphore,线程间交换数据用 Exchanger。

    3.避免锁竞争:

    使用原子类(如 AtomicInteger)替代锁。

    读写分离场景用 ReentrantReadWriteLock。

    4.线程池调优:

    根据任务类型选择队列(有界 vs 无界)。

    设置合理的拒绝策略(如 AbortPolicy、CallerRunsPolicy)。

    5.处理异步任务:

    使用 CompletableFuture 简化异步编程。

    分治任务用 ForkJoinPool 提升性能。

    http://www.dtcms.com/a/191649.html

    相关文章:

  1. Profibus DP主站转Profinet网关接E+H流量计与西门子plc通讯
  2. 【golang】DNS 资源记录(RR)接口
  3. PyTorch LSTM练习案例:股票成交量趋势预测
  4. uniapp微信小程序-长按按钮百度语音识别回显文字
  5. R语言的专业网站top5推荐
  6. 【Linux】动静态库的使用
  7. 边缘计算模块
  8. 专项智能练习(定义判断)_DA_02
  9. idea整合maven环境配置
  10. GPT-4o 遇强敌?英伟达 Eagle 2.5 视觉 AI 王者登场
  11. 电池组PACK自动化生产线:多领域电池生产的“智能引擎”
  12. 重磅发布!OpenAI 推出最新模型 GPT-4.1 系列!
  13. 2025全网首发:ComfyUI整合GPT-Image-1完全指南 - 8步实现AI图像创作革命
  14. 英迈国际Ingram Micro EDI需求分析
  15. 论文研读——《AnomalyGPT:使用大型视觉语言模型检测工业异常》
  16. IntelliJ IDEA 集成AI编程助手全解析:从Copilot到GPT-4o Mini的实践
  17. 山东大学计算机图形学期末复习7——CG11上
  18. 红黑树:数据世界的平衡守护者
  19. RTSP 播放器技术探究:架构、挑战与落地实践
  20. 投影仪基础知识及选购方向小记②
  21. RedHat7 如何更换yum镜像源
  22. 【java】synchronized关键字详解
  23. C语言中的指定初始化器
  24. 第四章:文件内容查看
  25. 二、IGMP
  26. 如何在 AWS 上构建支持 AVIF 的前端图片优化方案
  27. 全志F10c200开发笔记——移植uboot
  28. 使用java -jar命令指定VM参数-D运行jar包报错问题
  29. 为什么doris是实时的?
  30. 【React全栈进阶】从组件设计到性能优化实战指南