Java 并发知识点

Java 并发知识点

1. 线程状态

  • 新建(NEW):创建线程对象后进入此状态,无法获取 CPU 资源。
  • 就绪(RUNNABLE):调用 start() 方法后进入,等待获取 CPU 资源以运行。
  • 运行:获得 CPU 资源后执行代码。
  • 阻塞:因某些事件触发,如锁阻塞、等待唤醒、超时等待、IO 操作等,阻塞解除后回到就绪状态。
    • BLOCKED:获取同步锁失败,进入锁池等待。
    • WAITING:调用 wait() 方法后等待,需 notify()notifyAll() 唤醒。
    • TIMED_WAITING:调用 wait(long)sleep(long) 方法,时间到或被唤醒后就绪。
    • IO 阻塞:进行 IO 操作时让出 CPU 资源,操作结束后就绪。
  • 消亡(TERMINATED):线程代码执行结束,被销毁。

2. 线程池

核心参数
  • corePoolSize:核心线程数,闲时从阻塞队列取任务执行,不使用时不释放。
  • maximumPoolSize:最大线程数,核心线程和队列满后,可创建非核心线程,但总数不超此值。
  • keepAliveTime:非核心线程空闲时的存活时间。
  • unit:存活时间的时间单位。
  • workQueue:阻塞队列,核心线程满后,新任务存入队列。
  • threadFactory:使用工厂模式创建线程对象。
  • handler:拒绝策略,核心线程、队列和非核心线程都满时,处理新任务的策略。
拒绝策略
  • AbortPolicy:抛出 RejectedExecutionException 异常。
  • CallerRunsPolicy:提交任务的线程自行执行该任务。
  • DiscardOldestPolicy:用新任务替换队列中等待最久的任务。
  • DiscardPolicy:丢弃新提交的任务。
最大线程数设置

需综合考虑系统资源、任务性质等因素,一般可根据 CPU 核心数、IO 密集程度等进行估算。

3. 阻塞队列

  • 当核心线程满时,新任务存入的队列,避免内存溢出,常选用有界队列。
  • 常见阻塞队列:ArrayBlockingQueueLinkedBlockingQueue 等。

4. wait()sleep() 的区别

  • 共同点:都使当前线程放弃 CPU 资源,进入阻塞状态。
  • 归属不同sleep()Thread 类的静态方法,wait()Object 类的实例方法。
  • 唤醒时机sleep(long)wait(long) 时间到自动苏醒,wait()notify()notifyAll() 唤醒。
  • 锁持有情况sleep() 阻塞时持有锁,wait() 阻塞时释放锁。

5. 线程安全的集合类

  • Vector:使用 Synchronized 锁实现。
  • CopyOnWriteArrayListCopyOnWriteArraySet:使用写入复制算法,用 lock 锁实现。
  • ConcurrentHashMap:使用写入复制算法,用 lock 锁实现。

6. Lock

  • Synchronized 更灵活,是对其的补充,需手动加锁和解锁。
  • 实现类有 ReentrantLockReentrantReadWriteLock

7. synchronizedLock 的区别

  • 实现方式synchronized 是 Java 内置关键字,由 JVM 控制;Lock 是接口,有丰富 API。
  • 锁状态判断synchronized 无法判断,Lock 可以。
  • 锁释放synchronized 自动释放,Lock 手动释放。
  • 特性:两者都是可重入锁,synchronized 不可中断、非公平,Lock 可判断锁、可设置公平或非公平。
  • 适用场景synchronized 适合少量代码同步,Lock 适合大量同步代码。

8. Fail - Fast

  • 概念:对线程不安全集合迭代时,若其他线程修改集合结构或元素数量,抛出 ConcurrentModificationException
  • 原因:集合修改操作使 modCountexpectedModCount 不一致,遍历检测到就抛异常。

9. 取消正在执行的线程

可通过设置标志位、调用 interrupt() 方法等方式。

10. ReadWriteLock

  • 读写锁,分为读锁(共享锁)和写锁(独占锁)。
  • 读锁允许多线程同时访问,提高读取效率;写锁只允许一个线程访问,保证数据修改安全。

11. 千万级计算任务处理

使用分支合并计算(ForkJoin),将大任务拆分成小任务并行计算,最后合并结果。可使用 ForkJoinPool 实现。

12. ForkJoinPool

  • 特点是分叉合并和工作窃取,为每个线程分配独立队列,线程可从其他线程队列取任务执行。
  • ThreadPoolExecutor 的区别:都实现相关接口,可设置线程数;ForkJoinPool 有独立队列和工作窃取机制,适合处理大数据量任务。

13. 工作窃取

线程完成自己队列任务后,从其他未完成线程的队列尾部获取任务计算,减少竞争。

14. 双端队列

两端都可进行插入和获取操作的队列。

  • 非线程安全:LinkedListArrayDeque
  • 线程安全:ConcurrentLinkedDequeLinkedBlockingDeque

15. 函数式接口

  • 接口中只有一个抽象方法,可用 @FunctionalInterface 注解强制规定。
  • 好处是简化编程模型,可结合 lambda 表达式使用。

16. 常用函数式接口

  • Function<T, R>:函数型接口,有 R apply(T) 方法。
  • Predicate:判定型接口,有 boolean test(T) 方法。
  • Supplier:生产型接口,有 T get() 方法。
  • Consumer:消费型接口,有 void accept(T) 方法。

17. 锁的分类

  • 公平锁和非公平锁:公平锁按顺序获取锁,非公平锁支持抢占,SynchronizedReentrantLock 是非公平锁。
  • 独占锁和共享锁:独占锁一次只能被一个线程持有,如 Synchronized 等;共享锁可被多个线程持有,如 ReentrantReadWriteLock.ReadLock
  • 悲观锁和乐观锁:悲观锁读写数据都上锁,如 Synchronized 等;乐观锁读时不上锁,更新时判断数据是否被修改,Java 中常用 CAS 实现。

18. 读写锁

读锁共享,写锁独占,特点是读读不互斥、读写互斥、写写互斥。

19. 自旋锁

轻量级锁,线程未获得资源时自旋,减少资源消耗,自旋一定次数后进入阻塞状态,原子类使用自旋锁。

20. 偏向锁

认为多数情况下只有一个线程访问,出现竞争时升级为轻量级锁,JDK 1.6 后 SynchronizedLock 底层使用。

21. CAS

  • 比较并交换,保证变量原子操作,包含要修改的变量、预期值和新值。
  • 存在 CPU 开销大、不能保证代码块原子性和 ABA 问题。

22. ABA 问题及解决

  • 问题:CAS 操作中,值被修改后又改回原值,原线程认为值未变而继续操作。
  • 解决方法:使用原子引用(如 AtomicStampedReference)添加版本号判断。

23. Volatile

  • 修饰属性,底层通过内存屏障实现。
  • 作用是保证变量可见性和避免指令重排,但不能保证原子性,不能保证线程安全。

24. 指令重排

编译器或 CPU 为优化性能对指令重新排序,多线程中会带来可见性问题。

25. 内存屏障

  • 限制编译器和处理器指令重排,保证可见性和有序性。
  • 写屏障保证共享变量改动同步到主存,读屏障保证读取主存最新数据。

26. ThreadLocal

  • 为线程绑定变量,解决多线程访问共享变量问题,各线程变量隔离。
  • 实现原理是每个线程有 ThreadLocalMap,将 ThreadLocal 对象作为 key,变量作为 value 存储。
  • 可能出现内存泄漏和脏数据问题,使用后需调用 remove() 方法。

27. 并发、并行、串行

  • 串行:任务按顺序依次执行。
  • 并行:同一时刻多个任务同时执行,需多 CPU 或单 CPU 多核心支持。
  • 并发:多个任务同时执行,但同一时刻只有一个任务执行,任务抢占 CPU 资源。

28. 对象的组成

  • 对象头:包含 Mark Word(存储运行时数据)、Klass Word(指向类地址)和数组长度(数组对象有)。
  • 实例数据:对象的属性和值。
  • 对齐填充字节:使对象占用内存为 8 字节倍数。

29. 上下文切换

多线程编程中,线程时间片用完后保存状态,让给其他线程,下次切换回来再加载状态的过程,消耗 CPU 时间。

30. JVM 加锁过程

  • 无锁:无线程访问。
  • 偏向锁:一个线程加锁,无竞争,开启则写入线程 ID,未开启则进入轻量级锁。
  • 轻量级锁:多个线程竞争,偏向锁升级,用 CAS 维护原子性,竞争严重时膨胀为重量级锁。
  • 重量级锁:直接加锁,未获资源线程进入阻塞状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值