Java 线程池有哪些拒绝策略?回答重点一共提供了 4 种:
1)AbortPolicy,当任务队列满且没有线程空闲,此时添加任务会直接抛出 RejectedExecutionException 错误,这也是默认的拒绝策略。适用于必须通知调用者任务未能被执行的场景。
2)CallerRunsPolicy,当任务队列满且没有线程空闲,此时添加任务由即调用者线程执行。适用于希望通过减缓任务提交速...
你了解时间轮(Time Wheel)吗?有哪些应用场景?回答重点时间轮(Time Wheel) 是一种用于管理和调度大量定时任务的数据结构。它是一种高效的定时任务调度算法,主要用于优化任务调度的效率,特别是在需要处理大量定时任务时。
时间轮是一种环形的数据结构,通过将时间划分为若干个时间片(槽),每个时间片负责管理一定时间段(如秒、分钟等内的任务。
工作原理:
时间轮的中心是一个环形结构,...
什么是 Java 的 Timer?回答重点Java 的 Timer 是一个用于调度任务的工具类,用于在未来某个时刻执行任务或周期性地执行任务。Timer 类一般与 TimerTask 搭配使用,其中 TimerTask 是一个需要执行的任务。
适用于简单的定时任务,如定时更新、定期发送报告等。
扩展知识Timer 使用TimerTask 是 Timer 需要执行的任务,它是一个实现了 Run...
你使用过哪些 Java 并发工具类?回答重点比如:ConcurrentHashMap、AtomicInteger、Semaphore、CyclicBarrier、CountDownLatch、BlockingQueue 等等。
这个问题只要把你知道的一些并发类名字说出来就行了,然后等面试官选择其中一个去询问即可(一般需要结合简历中项目的业务场景,所以需要根据自己的业务提前准备)。
具体的并发...
什么是 Java 的 CyclicBarrier?回答重点CyclicBarrier 是一个同步辅助类,允许一组线程在执行某个任务时相互等待,直到所有线程都到达屏障(barrier)之后才继续执行。它的设计目的是解决多线程并发任务中需要同步的场景,确保所有参与的线程都在特定的点上完成执行,然后一起继续后续的任务。
扩展知识基本概念
屏障(Barrier):一个线程在调用 await() 方法...
什么是 Java 的 Semaphore?回答重点Semaphore (信号量)是 Java 并发包中的一个同步工具类,用于管理一组许可(permits)。每个许可可以被一个线程持有,当许可被持有时,其他线程需要等待才能获取许可。即可以限制同时访问特定资源的线程数量,确保在特定时刻只有有限数量的线程能够访问资源。
扩展知识基本概念:
许可(Permits):表示可以访问资源的线程数量。Sem...
什么是 Java 的 StampedLock?回答重点StampedLock 是 Java 8 引入的一个锁机制,与传统的 ReentrantLock 和 ReadWriteLock 相比,StampedLock 通过引入乐观读锁和时间戳(stamp)的概念,提升了读写性能,尤其是在读多写少的场景下。
核心特性:
写锁(write lock):独占模式的锁,和 ReentrantLock ...
什么是 Java 的 CompletableFuture?回答重点CompletableFuture 是 Java 8 引入的一个强大的异步编程工具。允许非阻塞地处理异步任务,并且可以通过链式调用组合多个异步操作。
核心特性:
异步执行:使用 runAsync() 或 supplyAsync() 方法,可以非阻塞地执行任务。
任务的组合:可以使用 thenApply()、thenAccep...
什么是 Java 的 ForkJoinPool?重点Java的ForkJoinPool 是Java 7引入的一个专门用于并行执行任务的线程池,它采用“分而治之”(divide and conquer)算法来解决大规模的并行问题。
核心机制:
Fork(分解):任务被递归分解为更小的子任务,直到达到不可再分的程度。
Join(合并):子任务执行完毕后,将结果合并,形成最终的解决方案。
工作...
什么是 Java 的 CountDownLatch?回答重点CountDownLatch 是 JUC 中的一个同步辅助类,它允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。CountDownLatch 通过一个计数器来实现,计数器的初始值由构造方法传入。每当一个线程完成工作后,计数器会递减。当计数器到达零时,所有等待的线程会被唤醒并继续执行。
主要功能:
等待事件完成:通过 a...
如何在 Java 中控制多个线程的执行顺序?回答重点在 Java 中控制多个线程的执行顺序有很多种方法:
1) CompletableFuture,它内部有 thenRun 的方法,假设我们现在有三个任务T1、T2、T3 需要按序执行,那么仅需使用以下伪代码即可:
123CompletableFuture.runAsync(() -> {do t1 sth}) ...
你使用过 Java 的累加器吗?回答重点在 Java 中累加器(Accumulator)一般指的是LongAdder 和 DoubleAdder 类,它们在高并发场景下比传统的 AtomicLong 更具优势。
LongAdder 和 DoubleAdder
LongAdder:适用于 long 类型的累加操作,提供了高效的累加功能,尤其是在多线程环境中。
DoubleAdder:适用于 d...
你使用过 Java 中的哪些阻塞队列?回答重点阻塞队列主要用来阻塞队列的插入和获取操作,当队列满了的时候插入操作会被阻塞,直到队列有空位。当队列为空的时候获取操作会被阻塞,直到队列有值。
常用在实现生产者和消费者场景,在笔试题中比较常见。
常见的阻塞队列包括:
ArrayBlockingQueue:一个有界队列,底层基于数组实现。需要在初始化时指定队列的大小,队列满时,生产者会被阻塞,队...
你使用过 Java 中的哪些原子类?回答重点Java 中的原子类是通过使用硬件提供的原子操作指令(如 CAS,Compare-And-Swap)来确保操作的原子性,从而避免线程竞争问题。
常用的原子类有以下几种:
AtomicInteger:用于操作整数的原子类,提供了原子性的自增、自减、加法等操作。
AtomicLong:与 AtomicInteger 类似,但用于操作 long 型数据...
Synchronized 和 ReentrantLock 有什么区别?回答重点Synchronized 是 Java 内置的关键字,实现基本的同步机制,不支持超时,非公平,不可中断,不支持多条件。
ReentrantLock 是 JUC 类库提供的,由 JDK 1.5 引入,支持设置超时时间,可以避免死锁,比较灵活,并且支持公平锁,可中断,支持多条件判断。
ReentrantLock 需要手...
当 Java 的 synchronized 升级到重量级锁后,所有线程都释放锁了,此时它还是重量级锁吗?回答重点当重量级锁释放了之后,锁对象是无锁的。
有新的线程来竞争的话又会从轻量级锁开始。
扩展知识我们都知道 synchronized 的锁升级,也听过锁升级之后不会降级,所以理所当然的认为当一个锁升级为重量级锁之后,任何线程再来争抢之后会走重量级锁的逻辑。
不会再从无锁到偏向锁到轻量级锁...
Java 中的 synchronized 轻量级锁是否会进行自旋?回答重点轻量级锁 CAS 失败了之后,不会有自旋操作,会直接进入重量级锁膨胀过程。
扩展知识关于 Synchronized 专门翻阅 JVM HotSpot 1.8 的源码来研究了了,那时候就发现有一个点,一个几乎网上所有文章包括《Java并发编程的艺术》也是这样说的一个点。
锁升级想必网上有太多文章说过了,这里提到当轻...
什么是 Java 中的锁自适应自旋?回答重点锁自适应自旋 是 Java 锁优化中的一种机制,用于减少线程在竞争锁时频繁挂起和恢复的开销。
自适应自旋的核心思想是,在锁争用较少的情况下,线程在进入等待状态前,先执行一段自旋操作(即短暂忙等),而不是立刻挂起线程。
在 Java 中 Syncronized 在争抢重量级锁时候会自旋。具体指的是在重量级锁时,一个线程如果竞争锁失败会进行自旋操作,说...
如何优化 Java 中的锁的使用?回答重点主要有以下两种常见的优化方法:
1)减小锁的粒度(使用的时间):
尽量缩小加锁的范围,减少锁的持有时间。即在必要的最小代码块内使用锁,避免对整个方法或过多代码块加锁。
使用更细粒度的锁,比如将一个大对象锁拆分为多个小对象锁,以提高并行度(参考 HashTable 和ConcurrentHashMap 的区别)。
对于读多写少的场景,可以使用读写锁(...
Java 中 ReentrantLock 的实现原理是什么?回答重点ReentrantLock 其实就是基于 AQS 实现的一个可重入锁,支持公平和非公平两种方式。
内部实现依靠一个 state 变量和两个等待队列:同步队列和等待队列。
利用 CAS 修改 state 来争抢锁。
争抢不到则入同步队列等待,同步队列是一个双向链表。
条件 condition 不满足时候则入等待队列等待,是个单...
说说 AQS 吧?回答重点
如果面试官问你为什么需要 AQS ,不要长篇大论,容易把自己和面试官绕进去。就这样简要的回答:
简单来说 AQS 就是起到了一个抽象、封装的作用,将一些排队、入队、加锁、中断等方法提供出来,便于其他相关 JUC 锁的使用,具体加锁时机、入队时机等都需要实现类自己控制。
它主要通过维护一个共享状态(state)和一个先进先出(FIFO)的等待队列,来管理线程对共...
什么是 Java 的 CAS(Compare-And-Swap)操作?回答重点CAS 是一种硬件级别的原子操作,它比较内存中的某个值是否为预期值,如果是,则更新为新值,否则不做修改。
工作原理:
比较(Compare):CAS 会检查内存中的某个值是否与预期值相等。
交换(Swap):如果相等,则将内存中的值更新为新值。
失败重试:如果不相等,说明有其他线程已经修改了该值,CAS 操作失败...
什么是 Java 内存模型(JMM)?回答重点Java 内存模型(Java Memory Model, JMM) 是 Java 虚拟机 (JVM) 定义的一种规范,用于描述多线程程序中变量(包括实例字段、静态字段和数组元素)如何在内存中存储和传递的规则。规范了线程何时会从主内存中读取数据、何时会把数据写回主内存。
JMM 的核心目标是确保多线程环境下的可见性、有序性和原子性,从而避免由于硬件...
什么是 Java 的 happens-before 规则?回答重点happens-before 规则是 Java 内存模型 (Java Memory Model, JMM) 中的核心概念,用于定义多线程程序中操作的可见性和顺序性。它通过指定一系列操作之间的顺序关系,确保线程间的操作是有序的,避免由于重排序或线程间数据不可见导致的并发问题。
happens-before 规则的主要规则:1)程...
你了解 Java 中的读写锁吗?回答重点读写锁,它允许多个线程同时读取共享资源,而在写操作时确保只有一个线程能够进行写操作(读读操作不互斥,读写互斥、写写互斥)。这种机制适合于读多写少的场景,因为它提高了系统的并发性和性能。
Java 中的 ReadWriteLock 是通过 ReentrantReadWriteLock 实现的,它提供了以下两种锁模式:
读锁(共享锁):允许多个线程同时获...
什么是 Java 中的原子性、可见性和有序性?回答重点1)原子性(Atomicity):
原子性指的是一个操作或一系列操作要么全部执行成功,要么全部不执行,期间不会被其他线程干扰。
2)可见性(Visibility):
可见性指的是当一个线程修改了某个共享变量的值,其他线程能够立即看到这个修改。
3)有序性(Ordering):
有序性指的是程序执行的顺序和代码的先后顺序一致。但在多线程环境...
Java 中的 final 关键字是否能保证变量的可见性?回答重点不可以。
你可能看到一些答案说可以保证可见性,那不是我们常说的可见性。
一般而言我们指的可见性是一个线程修改了共享变量,另一个线程可以立马得知更改,得到最新修改后的值。
而 final 并不能保证这种情况的发生,volatile 才可以。
而有些答案提到的 final 可以保证可见性,其实指的是 final 修饰的字段在构造...
什么是 Java 中的指令重排?回答重点指令重排是 Java 编译器和处理器为了优化性能,在保证单线程程序语义不变的情况下,对指令执行顺序进行调整的过程。在多线程环境下,指令重排可能导致线程之间的操作出现不同步或不可见的现象,因此 Java 提供了内存模型(JMM)和相关机制(如 volatile 和 synchronized)来限制这种行为,确保并发操作的正确性。
主要原因:
编译器优化:...
为什么在 Java 中需要使用 ThreadLocal?回答重点因为在多线程编程中,多个线程可能会同时访问和修改共享变量,导致线程安全问题。ThreadLocal 提供了一种简单的解决方案,使每个线程都有自己的独立变量副本,避免了多线程间的变量共享和竞争,从而解决了线程安全问题。
与通过加锁、同步块等传统方式来保证线程安全相比。ThreadLocal 不需要对变量访问进行同步,减少了上下文切...
Java 中的 ThreadLocal 是如何实现线程资源隔离的?回答重点ThreadLocal 提供了一种线程内独享的变量机制,使每个线程都能有自己独立的变量副本。每个线程内部维护一个 ThreadLocalMap,这个 ThreadLocalMap 用于存储线程独立的变量副本。ThreadLocalMap 以 ThreadLocal 实例作为键,以线程独立的变量副本作为值。不同线程通过 ...