JUC多线程核心知识点深度解析

article/2025/8/26 12:52:39

 最近正在复习Java八股,所以会将一些热门的八股问题,结合ai与自身理解写成博客便于记忆

本文将从以上10个经典面试问题来做juc多线程的解析

一、线程状态与流转机制

1. 六种线程状态(Java定义)

public enum State {NEW,           // 新建未启动RUNNABLE,      // 可运行(包含就绪和运行中)BLOCKED,       // 被阻塞(等待监视器锁)WAITING,       // 无限期等待(无时限的wait/join/park)TIMED_WAITING, // 限期等待(带时限的sleep/wait/join/park)TERMINATED     // 终止
}

2.关键转换场景:

start():NEW → RUNNABLE
获取锁失败:RUNNABLE → BLOCKED
Object.wait():RUNNABLE → WAITING
Thread.sleep(ms)`:RUNNABLE → TIMED_WAITING
任务结束/异常:RUNNABLE → TERMINATED

二、线程创建方式对比

1. 基础创建方式

// 方式1:继承Thread类
class MyThread extends Thread {public void run() {System.out.println("Thread running");}
}
new MyThread().start();// 方式2:实现Runnable接口
new Thread(() -> System.out.println("Runnable running")).start();// 方式3:实现Callable接口(可获取返回值)
FutureTask<String> task = new FutureTask<>(() -> "Callable result");
new Thread(task).start();
String result = task.get();

2. 生产环境推荐

线程池创建(推荐所有场景)
CompletableFuture(Java8+异步编程)
虚拟线程(Java19+轻量级线程)

三、多线程典型应用场景

1. 高并发处理

电商秒杀系统
即时通讯消息推送
金融交易订单处理

2. 异步任务

```java
// 异步日志记录
executor.execute(() -> logService.saveLog(logEntity));// 并行计算
List<Future<Result>> futures = IntStream.range(0, 10).mapToObj(i -> executor.submit(() -> compute(i))).collect(Collectors.toList());
```

3. 定时调度

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
scheduler.scheduleAtFixedRate(() -> {System.out.println("定时任务执行");
}, 1, 5, TimeUnit.SECONDS);

四、线程池核心机制

1. 七大构造参数

public ThreadPoolExecutor(int corePoolSize,      // 核心线程数int maximumPoolSize,   // 最大线程数long keepAliveTime,    // 空闲线程存活时间TimeUnit unit,         // 时间单位BlockingQueue<Runnable> workQueue, // 工作队列ThreadFactory threadFactory,       // 线程工厂RejectedExecutionHandler handler   // 拒绝策略
)

2. 执行流程图示


         提交任务
             │
             ▼
核心线程是否已满?──否─► 创建核心线程执行
             │是
             ▼
工作队列是否已满?──否─► 加入队列等待
             │是
             ▼
最大线程是否已满?──否─► 创建临时线程执行
             │是
             ▼
        执行拒绝策略

3. 拒绝策略对比

策略类行为适用场景
AbortPolicy(默认)抛出RejectedExecutionException需要感知任务拒绝的场景 
CallerRunsPolicy由提交线程直接执行任务不希望丢失任务的场景 
DiscardPolicy静默丢弃任务可容忍任务丢失的场景 
DiscardOldestPolicy丢弃队列最老任务并重试允许丢弃旧任务的场景       

五、线程池配置实践

1. 线程数设置公式

CPU密集型:corePoolSize = CPU核数 + 1
IO密集型:corePoolSize = CPU核数 × (1 + 平均等待时间/平均计算时间)

int cpuCores = Runtime.getRuntime().availableProcessors();
ThreadPoolExecutor executor = new ThreadPoolExecutor(cpuCores * 2,      // 核心线程数cpuCores * 4,      // 最大线程数60,                // 空闲线程存活时间(s)TimeUnit.SECONDS,new LinkedBlockingQueue<>(1000), // 有界队列new NamedThreadFactory("app-thread"), // 自定义线程命名new CallerRunsPolicy()          // 降级策略
);

2. 避免使用Executors

问题案例:

// 可能导致OOM(无界队列)
ExecutorService executor = Executors.newFixedThreadPool(10);// 最大线程数过大(Integer.MAX_VALUE)
ExecutorService executor = Executors.newCachedThreadPool();

六、生产环境监控指标

1. 关键监控项

指标监控方式健康标准
活跃线程数getActiveCount()≤ maximumPoolSize
任务队列大小getQueue().size()≤ 队列容量80%
已完成任务数getCompletedTaskCount()持续增长
拒绝任务数自定义RejectedExecutionHandler=0(理想情况)
线程空闲率(poolSize-activeCount)/poolSize20%~80%波动

七、常见问题解答

1:线程池为什么先填满队列再创建线程?

设计考量:
1. 线程创建销毁有开销
2. 任务排队通常比新建线程更高效
3. 避免线程数剧烈波动

2:如何选择工作队列?

选型指南:
ArrayBlockingQueue:固定大小,内存控制严格
LinkedBlockingQueue:无界/有界,吞吐量高
SynchronousQueue:直接传递,避免排队
PriorityBlockingQueue:优先级任务

3:核心线程为什么不会被回收?

设计意图:
1. 保持基础处理能力
2. 避免频繁创建销毁核心线程
3. 可通过`allowCoreThreadTimeOut(true)`改变默认行为


http://www.hkcw.cn/article/IoAtMBKIZE.shtml

相关文章

设计模式学习笔记

设计模式 一&#xff1a;分类&#xff1a; 创建型模式 用于描述“怎样创建对象”&#xff0c;它的主要特点是“将对象的创建与使用分离”。GoF&#xff08;四人组&#xff09;书中提供了单例、原型、工厂方法、抽象工厂、建造者等 5 种创建型模式。 结构型模式 用于描述如何将…

【地图】腾讯地图页面卡顿问题解决

目录 背景问题排查解决1. 页面是否使用 keep-alive 进行路由缓存2. 离开地图页面时&#xff0c;是否将地图清除 总结 背景 有的电脑没有显卡会出现如下问题&#xff1a; 系统打开有地图的页面&#xff0c;CPU 占用直线飙升到100%下不来&#xff0c;切到非地图页面&#xff0c;C…

一起看 I/O | Android 性能相关最新动态

作者 / Ben Weiss 过去几年来&#xff0c;我们一直致力于让性能提升工作变得更易上手、回报更高。我们将在本文中分享这一领域的最新发展动态。为您介绍基准配置文件、Android Studio 中的工具改进、库&#xff0c;以及我们如何让这项技术更好地在后台为您服务。此外&#xff0…

iPhone批量删除照片的方法

对于每一个iPhone用户来说&#xff0c;照片管理是一项日常而重要的任务。随着时间的积累&#xff0c;无数的照片快速填满了我们的存储空间&#xff0c;从美丽的风景到重要的家庭聚会&#xff0c;每一张照片都记录着我们生活中的瞬间。然而&#xff0c;当存储空间即将耗尽时&…

Gradle Kotlin 规范插件用于模块化结构 - 共享构建逻辑

Gradle Kotlin 规范插件用于模块化结构 - 共享构建逻辑 我们中的许多人都遇到过Groovy的困难&#xff0c;并习惯于将其转换为Kotlin DSL。 然后&#xff0c;作为Android工程师&#xff0c;在完全使用Kotlin编写的项目上工作是纯粹的喜悦。 我们假设采用基于功能的模块化应用程…

Gradle开发手册-高级篇之多模块项目创建

在进阶篇中详细讲解了gradle配置相关的详细内容。但是是基于单module的配置,在实际开发时基本全是多module类型的项目。所以本章我们就系统学习下如何构建多模块项目(父-子)以及相关的task内容。 基础篇:从概念以及广度上介绍下gradle的核心内容,并构建一个简单的java项目;…

Gradle的版本差异导致无法编译:Could not initialize class com.android.build.gradle.internal.TaskManager

运行项目报错:Could not initialize class com.android.build.gradle.internal.TaskManager 我这边的原因是少了SDK的包和JDK版本不对。 我们先区分下gradle version与gradle plugin version。如果对此不了解&#xff0c;经常会由于Gradle的版本号问题造成项目无法编译&#xf…

Gradle版本目录(Version Catalog)

Gradle版本目录(Version Catalog) “版本目录是一份依赖项列表&#xff0c;以依赖坐标表示&#xff0c;用户在构建脚本中声明依赖项时可以从中选择。” 我们可以使用版本目录将所有依赖项声明及其版本号保存在单个位置。这样&#xff0c;我们可以轻松地在模块和项目之间共享依…

android开发之NDK配置开发

1、打开项目后&#xff0c;一次点击Tools>SDK Manager 2、点击SDK Tools标签页 3、选中NDK&#xff08;Side by Side&#xff09;和CMake复选框 4、点击OK 此时系统会显示一个对话框&#xff0c;告诉你NDK软件包占用了多少磁盘空间 5、点击OK 6、安装完成后&#xff0c;点击…

如何在没有计算机的情况下将联系人从 iPhone 传输到安卓

如果您正在考虑从 iPhone 迁移到Android &#xff0c;您可能想知道如何在不丢失任何重要信息的情况下转移联系人。您可能还想避免使用电脑进行此过程。幸运的是&#xff0c;有几种方法可以教您如何在不使用电脑的情况下将联系人从 iPhone 迁移到Android &#xff0c;而且这些方…

如何将数据从 iPhone 传输到 vivo 的 4 种方法

在运行不同操作系统的 iPhone 和 Vivo 之间传输数据时&#xff0c;需要谨慎。廉价或不安全的在线解决方案可能会失败&#xff0c;并使您的个人数据面临风险。避免被“免费”和“快速”服务的承诺所诱惑&#xff0c;因为这可能会危及您的数据。 在本文中&#xff0c;我们整理了…

图片转换之heic转jpg(使用ImageMagick)

缘由&#xff1a;iphone的图库&#xff0c;用jpg拍照保存后内存占比较大&#xff0c;heic格式会微缩不少。问题来了&#xff0c;电脑不能直接小图预览heic。 分析&#xff1a;现在就是解决小图预览的问题&#xff08;大图用wps可以看&#xff09; 解决&#xff1a;查找了一些…

Android导入项目时Gradle下载速度慢\超时\失败解决方法

Android导入项目时Gradle下载速度慢\超时\失败解决方法 原因分析&#xff1a; 这是因为Gradle源服务器在国外&#xff0c;下载速度自然很慢 distributionUrlhttps\://services.gradle.org/distributions/gradle-7.3.3-bin.zip 解决方法&#xff1a; 最可靠的方法就是换源 &…

从 iPhone 传输到Android 3 种简单方法

使用 iPhone 多年后,也许您想切换到Android并尝试一些新的东西?不管您是否相信,如果您确实做出了这样的决定,您很可能会遇到将数据从 iPhone 传输到Android的问题。由于手机数据对于当今的人们来说非常重要,因此当您切换到另一部手机时丢失它是不明智的。 在本指南中,您…

Contactile三轴触觉力传感器的滑动与摩擦力计算能力

Contactile三轴触觉力传感器通过先进的技术设计&#xff0c;实现了滑动与摩擦力的精准计算。传感器通过分析滑动与振动信号的关联&#xff0c;动态计算摩擦系数&#xff0c;同时捕捉力、扭矩及初始滑动等多维数据。这种能力为机器人提供了高度灵活的触觉反馈&#xff0c;满足复…

国产分子动力学引擎——GPUMD本地部署教程:专为 NVIDIA GPU 加速设计

一、简介 GPUMD 是一款开源分子动力学模拟软件&#xff0c;由渤海大学樊哲勇教授团队主导开发&#xff0c;2017年首发1.0版本&#xff0c;持续迭代至3.9.4版本&#xff0c;是国内首个完全基于GPU加速的开源分子动力学软件&#xff0c;专为 NVIDIA GPU 加速设计。它使用 CUDA 提…

PostgreSQL 备份与恢复策略

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

2025年渗透测试面试题总结-匿名[校招]高级安全工程师(代码审计安全评估)(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。、 目录 匿名[校招]高级安全工程师(代码审计安全评估) 渗透基础 1. 自我介绍 2. SQL注入写Shell&#xff08;分数…

Cmake编译glog成功并在QT中测试成功步骤

glog是开源的日志记录系统&#xff0c;下载地址GitHub - google/glog: C implementation of the Google logging module 跟gflags有点相似&#xff0c;编译和测试过程比较周折&#xff0c;所以记录下来具体的编译和测试步骤。 编译环境&#xff1a;WindowsCmakeVs2022Qt5.14.…

【Linux】网络--传输层--深入理解TCP协议

个人主页~ 深入理解TCP协议 一、TCP数据传输问题1、发送数据丢包问题---重传机制&#xff08;一&#xff09;客户端数据发送丢包&#xff08;二&#xff09;服务器确认应答丢包&#xff08;三&#xff09;时间间隔问题 2、三次握手问题---奇数次握手&#xff08;一&#xff09;…