Java并发编程高频面试题

一、基础概念

1. 并行与并发的区别?

  • 并行:多个任务在多个CPU核心上同时执行(物理上同时)。
  • 并发:多个任务在单CPU核心上交替执行(逻辑上同时)。
  • 类比:并行是多个窗口同时服务,并发是一个窗口轮流服务。

2. 线程的创建方式?

  • 继承Thread:重写run()方法,通过start()启动。
  • 实现Runnable接口:更灵活,避免单继承限制。
  • 实现Callable接口:支持返回值和异常处理,配合FutureTask使用。

3. 线程的状态?

状态说明
NEW线程被创建但未启动
RUNNABLE线程正在执行或等待CPU资源
BLOCKED线程等待锁(进入同步代码块)
WAITING线程调用wait()/join()后等待唤醒
TIMED_WAITING超时等待(如sleep(long)
TERMINATED线程执行完毕或异常终止

4. sleep()wait()的区别?

特性sleep()wait()
所属类ThreadObject
锁行为不释放锁释放锁
唤醒方式超时自动唤醒需其他线程调用notify()唤醒
使用场景线程休眠线程间通信

5. 进程与线程的区别?

  • 进程:资源分配的最小单位(如内存、文件句柄)。
  • 线程:调度的最小单位,共享进程资源(如堆、方法区),但有独立栈和寄存器。
  • 协程:比线程更轻量级(如Kotlin的Coroutine)。

6.为什么用start()而非直接调用run()?

  • start()会创建新线程并执行run(),而直接调用run()仅在当前线程执行,无并发效果。

二、ThreadLocal

7. ThreadLocal的作用?

  • 线程隔离:为每个线程提供独立变量副本,避免共享数据冲突。
  • 典型场景:用户会话管理、数据库连接上下文传递。

8. ThreadLocal的实现原理?

  • 线程私有Map:每个线程维护一个ThreadLocal.ThreadLocalMap,键为ThreadLocal对象,值为线程变量。
  • 弱引用:键使用弱引用,防止内存泄漏。

9. ThreadLocal内存泄漏问题?

  • 原因:线程未及时调用remove(),导致Entryvalue强引用无法被回收。
  • 解决:使用try-finally确保调用remove()

三、Java内存模型(JMM)

9.JMM的核心是什么?

  • 定义线程间共享变量的访问规则,解决可见性、有序性、原子性问题。
  • 主内存:共享变量存储区。
  • 本地内存:线程私有的共享变量副本(抽象概念,对应CPU缓存等)。

10. JMM的三大特性?

  • 原子性:操作不可分割(如synchronized保证代码块原子性)。
  • 可见性:一个线程修改的值对其他线程立即可见(volatilesynchronized)。
  • 有序性:禁止指令重排序(volatile通过内存屏障实现)。

11. volatile的作用?

  • 可见性:强制将修改刷新到主内存,禁止缓存。
  • 有序性:通过内存屏障禁止指令重排序。

12. volatile的作用及实现原理?

  • 作用:保证可见性和禁止指令重排。
  • 原理:
    • 写操作后插入Store-Barrier,强制刷新主内存。
    • 读操作前插入Load-Barrier,强制从主内存读取。

四、锁机制

13. synchronized的使用方式?

  • 修饰方法:锁对象实例(非静态方法)或类(静态方法)。
  • 修饰代码块:指定锁对象,更细粒度控制。

14. synchronized的实现原理?

  • Monitor对象:每个Java对象关联一个监视器,线程通过获取Monitor实现互斥。
  • 锁升级:偏向锁 → 轻量级锁 → 重量级锁(基于CAS和自旋优化)。

15. synchronized与ReentrantLock的区别?

特性synchronizedReentrantLock
可重入自动支持需手动释放(unlock()
公平性非公平支持公平锁(通过构造函数)
锁获取阻塞等待支持tryLock()非阻塞获取
条件变量wait()/notify()支持Condition多条件变量

15. CAS的原理及问题?

  • 原理:Compare-And-Swap,通过原子指令实现无锁操作。
  • 问题
    • ABA问题:通过版本号(如AtomicStampedReference)解决。
    • 循环开销:长时间自旋消耗CPU。

五、并发工具类

16. CountDownLatch与CyclicBarrier的区别?

  • CountDownLatch:计数器递减至0时释放所有等待线程(一次性)。
  • CyclicBarrier:所有线程到达屏障后继续执行(可重用)。

17. Semaphore的作用?

  • 控制并发量:允许指定数量的线程同时访问资源。
  • 应用场景:限流、资源池管理。

六、线程池

18. 线程池的工作流程?

  1. 任务提交到线程池。
  2. 核心线程处理任务,空闲则创建新线程(未达最大线程数)。
  3. 任务队列已满且线程数达最大值时,触发拒绝策略。

提交任务 → 核心线程执行 → 队列缓冲 → 最大线程处理 → 拒绝策略。

19. 线程池参数配置?

  • corePoolSize:核心线程数。
  • maximumPoolSize:最大线程数。
  • keepAliveTime:空闲线程存活时间。
  • workQueue:阻塞队列(如LinkedBlockingQueue)。
  • handler:拒绝策略(如AbortPolicy)。

20. 线程池的拒绝策略?

  • AbortPolicy:抛异常(默认)。
  • CallerRunsPolicy:任务回退到调用线程执行。
  • DiscardPolicy:静默丢弃。
  • DiscardOldestPolicy:丢弃队列中最老的任务。

七、高级主题

21. 死锁的条件及避免?

  • 条件:互斥、持有并等待、不可抢占、循环等待。
  • 避免
    • 按顺序加锁。
    • 设置超时时间。
    • 使用ReentrantLocktryLock()

22. ConcurrentHashMap的线程安全机制?

  • 分段锁(JDK7):将数据分段,锁粒度细化。
  • CAS+synchronized(JDK8):数组+链表/红黑树结构,CAS保证原子性,synchronized保证同步。

23.CAS的问题及解决?

  • 问题:ABA问题、循环开销大。
  • 解决:AtomicStampedReference解决ABA,结合volatile减少循环。

八、代码实战

24. 手写双重校验单例模式?

public class Singleton {private static volatile Singleton instance; // 禁止指令重排private Singleton() {}public static Singleton getInstance() {if (instance == null) { // 第一次检查synchronized (Singleton.class) { // 加锁if (instance == null) { // 第二次检查instance = new Singleton(); // 初始化对象}}}return instance;}
}

volatile的必要性

  • 防止instance = new Singleton()的指令重排(先分配内存,再初始化对象,最后赋值引用)。
  • 若未使用volatile,其他线程可能在初始化完成前拿到未完全构造的对象。

25.线程的创建方式对比

// 继承Thread类
public class ThreadDemo extends Thread {@Overridepublic void run() {System.out.println("Thread running");}
}// 实现Runnable接口
public class RunnableDemo implements Runnable {@Overridepublic void run() {System.out.println("Runnable running");}
}// 实现Callable接口
public class CallableDemo implements Callable<String> {@Overridepublic String call() throws Exception {return "Callable result";}
}// 使用示例
public static void main(String[] args) throws Exception {// Threadnew ThreadDemo().start();// Runnablenew Thread(new RunnableDemo()).start();// Callable + FutureTaskFutureTask<String> futureTask = new FutureTask<>(new CallableDemo());new Thread(futureTask).start();System.out.println("Result: " + futureTask.get());
}

原理对比:

  • Thread类本身实现了Runnable接口,通过继承方式耦合度较高。
  • Runnable和Callable将任务与线程解耦,支持更灵活的扩展。
  • Callable通过FutureTask包装后,可通过get()方法获取异步结果。

26.ThreadLocal内存泄漏

public class ThreadLocalDemo {private static final ThreadLocal<String> threadLocal = new ThreadLocal<>();public static void main(String[] args) {threadLocal.set("value");// 未调用threadLocal.remove(),可能导致内存泄漏}
}

原理分析:

  • ThreadLocalMap的Entry以ThreadLocal为键(弱引用),若未手动remove(),当ThreadLocal对象被回收后,value仍被强引用在Entry中。
  • 解决方案
try {threadLocal.set("value");// 业务逻辑
} finally {threadLocal.remove(); // 在finally中确保清理
}

27.volatile的内存屏障

public class VolatileDemo {private volatile int x = 0;public void write() {x = 1; // 写操作后插入Store-Barrier}public void read() {int y = x; // 读操作前插入Load-Barrier}
}

内存屏障原理

  • Store-Barrier:确保屏障前的写操作全部刷新到主内存。
  • Load-Barrier:确保屏障后的读操作从主内存获取最新值。
  • 禁止指令重排:通过内存屏障阻止编译器和CPU对volatile变量操作的重排序。

28.synchronized vs ReentrantLock

// synchronized示例
public class SynchronizedDemo {public synchronized void method() {// 同步代码}
}// ReentrantLock示例
public class ReentrantLockDemo {private final ReentrantLock lock = new ReentrantLock();public void method() {lock.lock();try {// 同步代码} finally {lock.unlock();}}
}

29.CountDownLatch vs CyclicBarrier

// CountDownLatch示例
public class CountDownLatchDemo {public static void main(String[] args) throws InterruptedException {CountDownLatch latch = new CountDownLatch(2);new Thread(() -> {System.out.println("Task1 done");latch.countDown();}).start();new Thread(() -> {System.out.println("Task2 done");latch.countDown();}).start();latch.await(); // 等待两个任务完成System.out.println("All tasks done");}
}// CyclicBarrier示例
public class CyclicBarrierDemo {public static void main(String[] args) {CyclicBarrier barrier = new CyclicBarrier(2, () -> {System.out.println("Barrier reached");});new Thread(() -> {try {System.out.println("Task1 ready");barrier.await();System.out.println("Task1 continue");} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}}).start();new Thread(() -> {try {System.out.println("Task2 ready");barrier.await();System.out.println("Task2 continue");} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}}).start();}
}

核心区别

  • CountDownLatch:计数器递减到0后不可重置,用于“等待多个任务完成”。
  • CyclicBarrier:计数器达到阈值后重置,可循环使用,用于“多个线程同步执行”。

30.线程池工作流程

ExecutorService executor = new ThreadPoolExecutor(2, // corePoolSize4, // maximumPoolSize30, // keepAliveTimeTimeUnit.SECONDS,new ArrayBlockingQueue<>(10), // workQueueExecutors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
);

工作流程

  1. 提交任务 → 核心线程执行(未达corePoolSize时创建新线程)。
  2. 核心线程满 → 任务存入队列(如ArrayBlockingQueue)。
  3. 队列满 → 非核心线程执行(不超过maximumPoolSize)。
  4. 所有线程忙且队列满 → 触发拒绝策略(如AbortPolicy抛异常)。

31.CAS的ABA问题

AtomicInteger atomicInt = new AtomicInteger(100);
// 线程A:
int oldValue = atomicInt.get();
// 假设线程B将值改为101,再改回100
atomicInt.compareAndSet(oldValue, 200); // CAS成功,但值已被篡改

解决方案

AtomicStampedReference<Integer> stampedRef = new AtomicStampedReference<>(100, 0);
// 线程A:
int[] stampHolder = new int[1];
int oldValue = stampedRef.get(stampHolder);
int oldStamp = stampHolder[0];
// 线程B修改值并增加版本号
stampedRef.compareAndSet(oldValue, 101, oldStamp, oldStamp + 1);
// 线程A再次尝试CAS:
stampedRef.compareAndSet(oldValue, 200, oldStamp, oldStamp + 1); // 失败(版本号不匹配)

总结:以上题目覆盖Java并发编程核心知识点,建议重点掌握线程安全实现、锁优化、JMM原理、线程池调优等模块。面试时需结合源码和实际场景说明设计原理,体现对底层机制的理解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/77027.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LiT and Lean: Distilling Listwise Rerankers intoEncoder-Decoder Models

文章&#xff1a;ECIR 2025会议 一、动机 背景&#xff1a;利用LLMs强大的能力&#xff0c;将一个查询&#xff08;query&#xff09;和一组候选段落作为输入&#xff0c;整体考虑这些段落的相关性&#xff0c;并对它们进行排序。 先前的研究基础上进行扩展 [14,15]&#xff0c…

Python高级爬虫之JS逆向+安卓逆向1.2节: 变量与对象

目录 引言&#xff1a; 1.2.1 Python中的变量 1.2.2 变量的命名与可读性 1.2.3 Python中的对象 1.2.4 跟大神学高级爬虫安卓逆向 引言&#xff1a; 大神薯条老师的高级爬虫安卓逆向教程&#xff1a; 这套爬虫教程会系统讲解爬虫的初级&#xff0c;中级&#xff0c;高级知…

可发1区的超级创新思路(python 实现):一种轻量化的动态稀疏门控网络

首先声明,该模型为原创!原创!原创!且该思路还未有成果发表,感兴趣的小伙伴可以借鉴! 一、应用领域 视频异常检测、生成视频检测。 二、模型解析 该模型由1.关键帧动态选择机制、2.关键帧动态选择机制以及3.关键帧动态选择机制三大核心组件构成,形成端到端的视频异常…

使用NVM下载Node.js管理多版本

提示&#xff1a;我解决这个bug跟别人思路可能不太一样&#xff0c;因为我是之前好用&#xff0c;换个项目就不好使了&#xff0c;倦了 文章目录 前言项目场景一项目场景二解决方案&#xff1a;下载 nvm安装 nvm重新下载所需Node 版本nvm常用命令 项目结构说明 前言 提示&…

MySQL数据库经典面试题解析

1. MySQL 索引使用有哪些注意事项呢? 可以从三个维度回答这个问题:索引哪些情况会失效,索引不适合哪些场景,索引规则 索引哪些情况会失效 查询条件包含or,可能导致索引失效如何字段类型是字符串,where时一定用引号括起来,否则索引失效like通配符可能导致索引失效。联合…

C#结合SQLite数据库使用方法

一、关于SQLite SQLite 是一个轻量级的嵌入式关系型数据库管理系统&#xff08;RDBMS&#xff09;。与传统的数据库管理系统&#xff08;如 MySQL、PostgreSQL 或 SQL Server&#xff09;不同&#xff0c;SQLite 并不需要运行单独的服务器进程&#xff0c;它的数据库存储在一个…

深入解析 MySQL 中的日期时间函数:DATE_FORMAT 与时间查询优化

深入解析 MySQL 中的日期时间函数&#xff1a;DATE_FORMAT 与时间查询优化 在数据库管理和应用开发中&#xff0c;日期和时间的处理是不可或缺的一部分。MySQL 提供了多种日期和时间函数来满足不同的需求&#xff0c;其中DATE_FORMAT函数以其强大的日期格式化能力&#xff0c;…

如何深刻理解Reactor和Proactor

前言&#xff1a; 网络框架的设计离不开 I/O 线程模型&#xff0c;线程模型的优劣直接决定了系统的吞吐量、可扩展性、安全性等。目前主流的网络框架&#xff0c;在网络 IO 处理层面几乎都采用了I/O 多路复用方案(又以epoll为主)&#xff0c;这是服务端应对高并发的性能利器。 …

笔试专题(七)

文章目录 乒乓球筐&#xff08;哈希&#xff09;题解代码 组队竞赛题解代码 删除相邻数字的最大分数&#xff08;线性dp&#xff09;题解代码 乒乓球筐&#xff08;哈希&#xff09; 题目链接 题解 1. 两个哈希表 先统计第一个字符串中的字符个数&#xff0c;再统计第二个字…

清晰易懂的 Flutter 卸载和清理教程

以下是为 Flutter 彻底卸载与清理教程&#xff0c;覆盖 Windows、macOS、Linux 系统&#xff0c;步骤清晰无残留&#xff0c;确保完全删除 Flutter SDK、依赖工具及 IDE 配置。 一、通用步骤&#xff1a;确认 Flutter 安装方式 Flutter 通常通过以下方式安装&#xff1a; 手动…

关于反卷积

&#x1f9e0; 什么是反卷积&#xff1f; 反卷积&#xff08;Deconvolution&#xff09;&#xff0c;通常也称为转置卷积&#xff08;Transpose Convolution&#xff09;&#xff0c;是一种用于扩展输入特征图的操作&#xff0c;通常用于生成图像或上采样任务中。与标准卷积操…

【机器学习】ROC 曲线与 PR 曲线

目录 一、混淆矩阵&#xff1a;分类评估的基础 二. ROC 曲线 (Receiver Operating Characteristic Curve) 三. PR 曲线 (Precision-Recall Curve) 3.1 核心思想 4. 何时使用 ROC 曲线和 PR 曲线&#xff1f; 实验结果 6. 总结 在机器学习的分类任务中&#xff0c;我们训…

Python高阶函数-map

map() 是 Python 内置的一个高阶函数&#xff0c;它接收一个函数和一个可迭代对象作为参数&#xff0c;将函数依次作用在可迭代对象的每个元素上&#xff0c;并返回一个迭代器&#xff08;Python 3.x 中&#xff09;。 基本语法 map(function, iterable, ...)function: 应用于…

上海餐饮市场数据分析与可视化

上海作为中国的经济中心和国际化大都市,其餐饮市场具有高度的多样性和竞争性。随着消费者需求的不断变化,餐饮行业的从业者和投资者需要深入了解市场现状和趋势,以便制定更有效的商业策略。本文将通过数据分析和可视化技术,深入探讨上海餐饮市场的现状和趋势,为餐饮从业者…

MySQL基础 [五] - 表的增删查改

目录 Create&#xff08;insert&#xff09; Retrieve&#xff08;select&#xff09; where条件 ​编辑 NULL的查询 结果排序(order by) 筛选分页结果 (limit) Update Delete 删除表 截断表&#xff08;truncate&#xff09; 插入查询结果&#xff08;insertselect&…

SQL:Primary Key(主键)和Foreign Key(外键)

目录 1. Key&#xff08;键&#xff09; 2. Index&#xff08;索引&#xff09; 3.Key和Index的区别 4. Primary Key&#xff08;主键&#xff09; 5. Foreign Key&#xff08;外键&#xff09; 6.主键和外键的关系 温馨提示&#xff1a; 闪电按钮不同的执行功能 首先&…

2025年- H1-Lc109-160. 相交列表--java版

1.题目描述 2.思路 “双指针切换链表头” 思路一&#xff1a;双指针路径对齐 while (pA ! pB) { pA (pA null) ? headB : pA.next; pB (pB null) ? headA : pB.next; } 让两个指针走相同的总路径长度&#xff01; 设&#xff1a; 链表 A 独有部分长度是 lenA 链表 B …

PyTorch 深度学习 || 6. Transformer | Ch6.3 Transformer 简单案例

1. 简单案例 这个代码是一个简单的 Transformer 模型的实现,这个例子展示了一个基本的序列到序列(seq2seq)任务,比如将一个数字序列转换为另一个数字序列。可以用于学习和理解 Transformer 的基本结构和工作原理。 import torch import torch.nn as nn import math# 位置…

基础算法篇(4)(蓝桥杯常考点)—数据结构(进阶)

前言 这期将会讲到基础算法篇里面的数据结构&#xff08;进阶&#xff09;&#xff0c;主要包括单调栈&#xff0c;单调队列&#xff0c;并查集&#xff0c;扩展域并查集&#xff0c;带权并查集&#xff0c;字符串哈希&#xff0c;Trie树。 数据结构(进阶&#xff09;正文 单…

【AI学习】初步了解Gradio

Gradio 是一个开源的 Python 库&#xff0c;专注于快速构建交互式 Web 界面&#xff0c;特别适用于机器学习模型、数据科学项目或任意 Python 函数的演示与部署。它通过极简的代码实现前后端一体化&#xff0c;无需前端开发经验即可创建功能丰富的应用。以下是 Gradio 的核心特…