1.线程状态

请解释 Java 中线程的几种状态,并描述每种状态的特点和转换条件。

  • NEW(新建):线程被创建,但尚未启动。
  • RUNNABLE(可运行):线程正在运行,可能在执行代码,也可能等待操作系统资源。
  • BLOCKED(阻塞):线程在等待监视器锁,以便进入同步块/方法。
  • WAITING(等待):线程等待另一个线程显式地唤醒它(例如,Object.wait()Thread.join())。
  • TIMED_WAITING(计时等待):线程等待另一个线程在指定的时间内唤醒它(例如,Thread.sleep()Object.wait(long timeout))。
  • TERMINATED(终止):线程已完成执行。

线程状态的转换条件包括线程的启动、资源竞争、同步块/方法的进入与退出、以及超时等。

2.synchronized 和 ReentrantLock

synchronizedReentrantLock 有什么区别?在什么情况下会选择使用 ReentrantLock

  • synchronized:是Java中的内置同步机制,修饰方法代码块,使用对象内部的监视器锁。简单易用,但功能有限(如不能尝试锁定、不能定时锁定)。
  • ReentrantLock:是 java.util.concurrent.locks 包中的锁,具有更多的高级功能,如可重入、可定时、可中断的锁定方式,支持公平锁和非公平锁

选择 ReentrantLock 的情况

  • 需要尝试锁定或定时锁定。
  • 需要公平锁定(顺序锁定)。
  • 需要更灵活的锁定机制和条件变量(例如 Condition)。

3.线程池

请说明 ThreadPoolExecutor 类的核心参数及其作用。你会如何调整线程池的配置来应对高并发的需求?

ThreadPoolExecutor 类的核心参数:

  • corePoolSize:核心线程数,线程池中始终保持存活的线程数。
  • maximumPoolSize:最大线程数,线程池中允许的最大线程数。
  • keepAliveTime:线程空闲时间,当线程数超过 corePoolSize 时,超时未任务的线程会被终止。
  • unit:keepAliveTime 的时间单位。
  • workQueue:任务队列,保存等待执行的任务。
  • threadFactory:线程工厂,创建新线程的方式。
  • handler:拒绝策略,当任务无法提交到线程池时的处理方式。

高并发配置建议

  • 根据任务类型调整 corePoolSize 和 maximumPoolSize。
  • 选择合适的队列(有界/无界)避免资源耗尽。
  • 使用合适的拒绝策略(如 CallerRunsPolicy)以防止任务丢失。

4.Future 和 CompletableFuture

FutureCompletableFuture 有何区别?在什么情况下你会选择使用 CompletableFuture

  • Future:表示一个异步计算的结果,可以通过 get() 方法获取计算结果,但会阻塞直到任务完成。适用于简单的异步任务。
  • CompletableFuture:扩展了 Future,提供了更丰富的 API 来进行异步任务的组合和处理(如 thenApplythenAccept)。支持链式调用和异常处理

使用 CompletableFuture 的情况

  • 需要进行多个异步任务的组合。
  • 需要非阻塞地处理异步结果。
  • 需要处理异步计算的异常。

5.阻塞队列

请介绍几种常用的阻塞队列及其适用场景。

常用的阻塞队列:

  • ArrayBlockingQueue:基于数组的有界阻塞队列。
  • LinkedBlockingQueue:基于链表的有界或无界阻塞队列。
  • PriorityBlockingQueue:支持优先级排序的无界阻塞队列。
  • DelayQueue:支持延时获取元素的无界阻塞队列。
  • SynchronousQueue:不存储元素的队列,每个插入操作必须等待对应的移除操作。

适用场景

  • ArrayBlockingQueue:固定容量的场景,避免队列过大。
  • LinkedBlockingQueue:需要动态增长的队列长度场景。
  • PriorityBlockingQueue:需要优先级处理的场景。
  • DelayQueue:需要延迟执行的任务调度场景。
  • SynchronousQueue:生产者和消费者一对一交互的场景。

6.CAS

什么是 CAS(Compare-And-Swap)?它是如何在 Java 中实现的?请描述其优缺点。

CAS(Compare-And-Swap)

  • CAS 是一种无锁算法,用于实现原子操作。通过比较内存中的某个值与预期值,如果相同则修改成新值,否则不修改。
  • 在 Java 中,CAS 通过 sun.misc.Unsafe 类中的方法实现(如 compareAndSwapInt)。

优点

  • 高效,无需阻塞线程。
  • 适合在多线程环境下保证数据一致性。

缺点

  • 可能会导致忙等待(如果 CAS 操作频繁失败)。
  • 不适合复杂的同步场景(如需要维护多个变量的一致性)。