Java线程池面试题整理总结【实习打卡01】

2023-11-17

ThreadLocal

GC 之后 key 是否为 null?

不一定。

(1)当使用new ThreadLocal<>().set(s); 定义threadlocal时,没有在栈中声明一个变量指向他,那他就是只被弱引用。在gc后,那这个threadlocal就会被回收,key为null,value还一直在,就会造成内存泄漏,所以注意在使用完threadlocal后一定要调用remove方法,避免因为key为null造成内存泄漏。

(2)当使用ThreadLocal<object> threadLocal = new ThreadLocal<>();方式定义时,相当于栈中存在一个变量threadLocal指向这个对象,形成强引用,即使在entry中,作为key是弱引用,但是在栈中一直有一个名为“threadLocal”的变量在指向他,存在强引用,所以这种情况下不会导致key为空。但是只要该变量所在的方法执行完之后,threadLocal变量消失,只剩一个弱引用,那么key也还是会被清理变成null。

为什么key使用弱引用?

如果使用强引用,当ThreadLocal 对象的引用(强引用)被回收了,ThreadLocalMap本身依然还持有ThreadLocal的强引用,如果没有手动删除这个key ,则ThreadLocal不会被回收,所以只要当前线程不消亡,ThreadLocalMap引用的那些对象就不会被回收, 可以认为这导致Entry内存泄漏。

ThreadLocalMap扩容机制

ThreadLocalMap.set()方法的最后,如果执行完启发式清理工作后,未清理到任何数据,且当前散列数组中Entry的数量已经达到了列表的扩容阈值(len*2/3),就开始执行rehash()逻辑:这里首先是会进行探测式清理工作,从table的起始位置往后清理,table中可能有一些keynullEntry数据被清理掉,此时通过判断size >= threshold * 3/4 来决定是否扩容。

接着看看具体的resize()方法,为了方便演示,扩容后的tab的大小为oldLen * 2,重新计算hash位置,然后放到新的tab数组中,如果出现hash冲突则往后寻找最近的entrynull的槽位,遍历完成之后,oldTab中所有的entry数据都已经放入到新的tab中了。

使用ThreadLocal的时候,在异步场景下无法给子线程共享父线程中创建的线程副本数据

为了解决这个问题,JDK 中还有一个InheritableThreadLocal类,实现原理是子线程是通过在父线程中通过调用new Thread()方法来创建子线程,Thread#init方法在Thread的构造方法中被调用。在init方法中拷贝父线程数据到子线程中。

ThreadLocal项目中使用实战

  1. 储存用户token
  2. traceId链路调用

在这里插入图片描述

ThreadPoolExecutor

ThreadPoolExecutor饱和策略定义

如果当前同时运行的线程数量达到最大线程数量并且队列也已经被放满了任务时,ThreadPoolTaskExecutor 定义一些策略:

  • ThreadPoolExecutor.AbortPolicy:(默认情况)抛出 RejectedExecutionException来拒绝新任务的处理。
  • ThreadPoolExecutor.CallerRunsPolicy:调用执行自己的线程运行任务,也就是直接在调用execute方法的线程中运行(run)被拒绝的任务,如果执行程序已关闭,则会丢弃该任务。因此这种策略会降低对于新任务提交速度,影响程序的整体性能。如果您的应用程序可以承受此延迟并且你要求任何一个任务请求都要被执行的话,你可以选择这个策略。
  • ThreadPoolExecutor.DiscardPolicy:不处理新任务,直接丢弃掉。
  • ThreadPoolExecutor.DiscardOldestPolicy:此策略将丢弃最早的未处理的任务请求。

线程池创建两种方式

方式一:通过ThreadPoolExecutor构造函数来创建(推荐)。

方式二:通过 Executor 框架的工具类 Executors 来创建。

  1. FixedThreadPool:该方法返回一个固定线程数量的线程池。线程池中的线程数量始终不变。当有一个新的任务提交时,线程池中若有空闲线程,则立即执行。若没有,则新的任务会被暂存在一个任务队列中,待有线程空闲时,便处理在任务队列中的任务。
  2. SingleThreadExecutor 该方法返回一个只有一个线程的线程池。若多余一个任务被提交到该线程池,任务会被保存在一个任务队列中,待线程空闲,按先入先出的顺序执行队列中的任务。
  3. CachedThreadPool 该方法返回一个可根据实际情况调整线程数量的线程池。线程池的线程数量不确定,但若有空闲线程可以复用,则会优先使用可复用的线程。若所有线程均在工作,又有新的任务提交,则会创建新的线程处理任务。所有线程在当前任务执行完毕后,将返回线程池进行复用。
  4. ScheduledThreadPool:该返回一个用来在给定的延迟后运行任务或者定期执行任务的线程池。

方式二不推荐,因为:

FixedThreadPoolSingleThreadExecutor:使用的是无界LinkedBlockingQueue,任务队列最大长度为 Integer.MAX_VALUE,可能堆积大量的请求,从而导致 OOM。

CachedThreadPool:使用的是同步队列 SynchronousQueue,没有容量,当没有空闲线程时,就立即申请线程, 允许创建的线程数量为 Integer.MAX_VALUE ,可能会创建大量线程,从而导致 OOM。

ScheduledThreadPoolSingleThreadScheduledExecutor : 使用的无界的延迟阻塞队列DelayedWorkQueue, 添加元素满了之后会自动扩容原来容量的 1/2,即永远不会阻塞,任务队列最大长度为 Integer.MAX_VALUE,可能堆积大量的请求,从而导致 OOM。

DelayedWorkQueue 的内部元素并不是按照放入的时间排序,而是会按照延迟的时间长短对任务进行排序,内部采用的是“堆”的数据结构

线程池原理分析

在这里插入图片描述

Runnable vs Callable

Runnable 接口不会返回结果或抛出检查异常,但是 **Callable 接口 **可以。

工具类 Executors 可以实现将 Runnable 对象转换成 Callable 对象,属于是转换器模式。

submit vs execute区别

execute()方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功与否;

submit()方法用于提交需要返回值的任务。线程池会返回一个 Future 类型的FutureTask对象,通过 Futureget()方法来获取返回值,get()方法会阻塞当前线程直到任务完成,而使用 get(long timeout,TimeUnit unit)方法的话,如果在 timeout 时间内任务还没有执行完,就会抛出 java.util.concurrent.TimeoutException

shutdown() VS shutdownNow()

  • shutdown() :关闭线程池,线程池的状态变为 SHUTDOWN。线程池不再接受新任务了,但是队列里的任务得执行完毕
  • shutdownNow() :关闭线程池,线程的状态变为 STOP线程池会终止当前正在运行的任务,并停止处理排队的任务并返回正在等待执行的 List

isTerminated() VS isShutdown()

  • isShutDown 当调用 shutdown() 方法后返回为 true。
  • isTerminated 当调用 shutdown() 方法后,并且所有提交的任务完成后返回为 true

ScheduledThreadPoolExecutor 和 Timer 对比

  • Timer 对系统时钟的变化敏感,ScheduledThreadPoolExecutor不是;
  • Timer 只有一个执行线程,因此长时间运行的任务可以延迟其他任务。 ScheduledThreadPoolExecutor 可以配置任意数量的线程。 此外,如果你想(通过提供 ThreadFactory),你可以完全控制创建的线程;
    ScheduledThreadPoolExecutor 可以配置任意数量的线程。 此外,如果你想(通过提供 ThreadFactory),你可以完全控制创建的线程;
  • TimerTask 中抛出的运行时异常会杀死一个线程,从而导致 Timer 死机即计划任务将不再运行。ScheduledThreadExecutor 不仅捕获运行时异常,还允许您在需要时处理它们(通过重写 afterExecute 方法ThreadPoolExecutor)。抛出异常的任务将被取消,但其他任务将继续运行。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java线程池面试题整理总结【实习打卡01】 的相关文章

  • 在 Java Swing 中检测 JScrollPane 上的 mouseClick 事件

    如果我有这样的东西 我可以使用布尔标志 performAdjustment 控制自动滚动 static boolean performAdjustment true JTextArea textArea new JTextArea JScr
  • V8 如何管理它的堆?

    我知道V8的垃圾收集在工作时 会从GC的root开始追踪 这样无法到达的对象就会被标记然后被清除 我的问题是GC是如何遍历那些对象的 必须有一个数据结构来存储所有可达或不可达的对象 位图 链接表 顺便说一句 JVM 也做同样的事情吗 艾伦秀
  • 以编程方式将 PEM 证书导入 Java KeyStore

    我有一个由两个文件 crt 和 key 组成的客户端证书 我希望将其导入到 java KeyStore 中 然后在 SSLContext 中使用 以通过 Apache 的 HTTPClient 发送 HTTP 请求 但是 我似乎找不到一种以
  • 使用多个构造函数创建不可变类

    我正在阅读这一页 https docs oracle com javase tutorial essential concurrency imstrat html关于在 Java 中创建不可变类 并决定根据页面上概述的规范修改我正在编写的类
  • java“void”和“非void”构造函数

    我用 java 编写了这个简单的类 只是为了测试它的一些功能 public class class1 public static Integer value 0 public class1 da public int da class1 v
  • 如何解决错误:java.lang.ClassNotFoundException:io.netty.util.concurrent.GenericFutureListener?

    昨天我第一次尝试用 Java 制作 Prometheus 客户端 从 Python 开始 最后是 GoLang 是否找到示例 import io prometheus client Counter import io prometheus
  • 如何在 OpenAPI 3.0 中定义字节数组

    我正在将 API 从 Swagger 2 0 迁移到 OpenAPI 3 0 在 DTO 中 我有一个指定为字节数组的字段 Swagger 对 DTO 的定义 Job type object properties body type str
  • 如何消除警告:使用“$”而不是“.”对于 Eclipse 中的内部类

    我是 Android 开发新手 当我将 eclipse 和 Android SDK 更新到最新版本后 我收到警告 Use instead of for inner classes or use only lowercase letters
  • 独占锁定ConcurrentHashMap

    我知道不可能锁定 ConcurrentHashMap 进行独占访问 但是 我找不到原因 是因为构成CHM的 Segment 没有被api公开吗 据推测 如果是的话 客户端代码可以执行 交接 锁定 Cheers 我知道不可能锁定 Concur
  • grails 上的同步块在 Windows 上有效,但在 Linux 上无效

    我有一个 grails 应用程序 它依赖于服务中的同步块 当我在 Windows 上运行它时 同步按预期工作 但当我在 ams linux 上运行时 会出现 StaleObjectStateException 该问题在以下示例中重现 cla
  • 如何在将数据发送到 Firebase 数据库之前对其进行加密?

    我正在使用 Firebase 实时数据库制作聊天应用程序 我知道 Firebase 非常安全 只要您的规则正确 但我自己可以阅读使用我的应用程序的人的所有聊天记录 我想阻止这种情况 为此我需要一种解密和加密方法 我尝试使用凯撒解密 但失败了
  • .class 与 .java

    class 文件和 java 文件有什么区别 我正在尝试让我的小程序工作 但目前我只能在 Eclipse 中运行它 还不能嵌入 HTML 谢谢 编辑 那么如何使用 JVM 进行编译呢 class 文件是编译后的 java 文件 java 都
  • 哪种 Java DOM 包装器是最好或最受欢迎的? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • @TestPropertySource 不适用于 Spring 1.2.6 中使用 AnnotationConfigContextLoader 的 JUnit 测试

    似乎我在 Spring 4 1 17 中使用 Spring Boot 1 2 6 RELEASE 所做的任何事情都不起作用 我只想访问应用程序属性并在必要时通过测试覆盖它们 无需使用 hack 手动注入 PropertySource 这不行
  • 如何计算文件中单词的长度?爪哇

    我正在尝试编写一个代码来计算文件中特定长度的单词数 例如 How are you 会打印 Proportion of 3 letter words 100 3 words 我想计算长度为 1 2 3 4 5 6 7 8 9 10 11 12
  • java中的比较器链

    正在阅读Oracle 关于接口的 Java 教程 https docs oracle com javase tutorial java IandI createinterface html其中给出了一个例子Card 打牌 我试图理解接口中的
  • Scala repl 抛出错误

    当我打字时scala在终端上启动 repl 它会抛出此错误 scala gt init error error while loading AnnotatedElement class file usr lib jvm java 8 ora
  • Java SE + Spring Data + Hibernate

    我正在尝试使用 Spring Data Hibernate 启动 Java SE 应用程序 并且到目前为止已经完成了以下操作 配置文件 Configuration PropertySource classpath hibernate pro
  • JDK 7 的快速调试/调试构建

    我正在寻找 JDK 的调试 或者我猜他们称之为快速调试构建 以启用在运行时生成的打印程序集以及查找性能问题时所需的其他诊断 就目前情况而言 我似乎找不到可以直接使用的 现成的 快速调试构建二进制包 有人可以帮我提供下载链接 或者至少提供有关
  • 日期时间解析异常

    解析日期时 我的代码中不断出现异常错误 日期看起来像这样 Wed May 21 00 00 00 EDT 2008 这是尝试读取它的代码 DateTimeFormatter formatter DateTimeFormatter ofPat

随机推荐

  • 区块链优秀gitbook资料

    docker 从入门到实践 https yeasy gitbooks io docker practice content image list html go 语言圣经 https docs hacknode org gopl zh ch
  • 双向链表(数据结构)(C语言)

    目录 概念 带头双向循环链表的实现 前情提示 双向链表的结构体定义 双向链表的初始化 关于无头单向非循环链表无需初始化函数 顺序表 带头双向循环链表需要的思考 双向链表在pos位置之前插入x 双向链表的打印 双链表删除pos位置的结点 双向
  • 学习总结4.1 Linux文件权限修改

    Linux系统中的每个文件都有访问许可权限 文件的访问权限分为只读 只写和可执行三种 只读权限表示只允许读其内容 而禁止对其做任何的更改操作 只写权限表示允许修改文件的内容 可执行权限表示允许将该文件作为一个程序执行 每一文件的访问权限都有
  • c/c++笔试面试题_6

    几个简单的c 面试题 2006 10 14 14 50 今天偶然看见这几个面试题 很有感触 想起一年前自己的求职经历 1 引言 本文的写作目的并不在于提供C C 程序员求职面试指导 而旨在从技术上分析面试题的内涵 文中的大多数面试题来自各大
  • 谷歌浏览器Google Chrome离线版(持续更新中)

    谷歌浏览器官方正式版采用自主研发Chromium内核 它是全球受欢迎的谷歌浏览器电脑版 追求速度 隐私安全的网络浏览器 而Google Chrome浏览器离线版更可以在无网络的情况下安装 一 在线版和离线版区别 在线版 即下载官方下载的一个
  • 服务链路追踪(Spring Cloud Sleuth)

    sleuth 英 slu 美 slu n 足迹 警犬 侦探vi 做侦探 微服务架构是一个分布式架构 它按业务划分服务单元 一个分布式系统往往有很多个服务单元 由于服务单元数量众多 业务的复杂性 如果出现了错误和异常 很难去定位 主要体现在
  • java中使用spark如何将column多列合为一列

    接下来介绍几种使用spark将DataFrame中一行的多列合并到一列中 并且该列以不同的类型展示保存 1 建立dataset 自己需要连接的mongo库 private static String datasource 自己需要连接的mo
  • 第十课.图片风格迁移和GAN

    目录 Neural Style Transfer Neural Style Transfer原理 准备工作 定义模型并加载预训练的模型参数 训练target以及结果可视化 生成对抗网络GAN GAN原理 GAN生成Mnist 准备工作 模型
  • 博客系统文章的数据库存储方式

    在通常的博客系统中 我们发表文章的时候 在数据库中存储的一般不仅仅是文章的文字 还包括文章的样式 而且很多时候都是所见即所得的效果 这就要求我们以html 文字这样存进数据库中 通过查找资料 可以用专门的文字编辑器可以实现 使用方法如下 F
  • 系统架构设计师之网络安全-各个层次的网络安全保障

    系统架构设计师之网络安全 各个层次的网络安全保障
  • Map集合知识点整理

    目录 一 Map集合概述 1 特点 2 Map集合的基本功能 二 实现类HashMap集合 1 概述 2 常用方法总结 3 HashMap的底层实现 4 LinkedHashMap 5 TreeMap 三 Map集合的遍历方式 四 案例演示
  • 文献管理软件--zotero基本使用

    文章目录 一 下载与安装 1 下载插件 以火狐浏览器为例 2 注册账户 3 下载桌面版 二 文献导入 1 新建文件 2 导入文献 3 本地导入 4 支持批量下载 三 文献管理 1 添加标签 2 添加子目录 3 添加笔记 四 添加插件 五 数
  • MyBatis的逆向工程

    MyBatis的逆向工程 正向工程 先创建Java实体类 由框架负责根据实体类生成数据库表 Hibernate是支持正向工程的 逆向工程 先创建数据库表 由框架负责根据数据库表 反向生成如下资源 Java实体类 Mapper接口 Mappe
  • 迭代法求解线性方程组(C++实现)

    本系列是数值分析相关算法的文章 这次用迭代法求解线性方程组 不同于上次用高斯消元法之类的求解 迭代法对于稀疏矩阵方程组的运算 会大大提高 而如果用高斯相关的算法求解 会浪费大量资源计算无用的东西 所以有必要研究此算法 本文章主要使用了3个算
  • android之service

    Service的启动有两种方式 context startService 和 context bindService 通过startService 启动的服务处于 启动的 状态 一旦启动 service就在后台运行 即使启动它的应用组件已经
  • Matlab2023a最新详解

    MATLAB 2023版的深度学习工具箱 提供了完整的工具链 使您能够在一个集成的环境中进行深度学习的建模 训练和部署 与Python相比 MATLAB的语法简洁 易于上手 无需繁琐的配置和安装 让您能够更快地实现深度学习的任务 MATLA
  • 【CTF/MISC】图片隐写题(binwalk/foremost/010editer配合使用)

    图片隐写 题目 解题思路 binwalk工具查看是否有隐藏文件 foremost工具分离文件 010editer查看二进制数据 寻找解压密码 解题心得 题目连接 题目 题目是一张图片 寻找题目中隐藏的flag 解题思路 一般来说我碰到图片隐
  • SSM框架下实现简单增删查改的具体细节(代码)

    UserInfo public class UserInfo private int id private String username private String password public int getId return id
  • 电子检测报告如何盖骑缝章?

    检测评估报告通常有多页 几十页的报告也不少见 文件中除了要在检测机构盖公章处盖章 还需要盖骑缝章 为了防范风险 防止报告内容被更换的情况 就需要骑缝章的加盖来保证检测报告的整体性 下面以微签为例 展示一下电子检测报告如何盖骑缝章 微签在检测
  • Java线程池面试题整理总结【实习打卡01】

    ThreadLocal GC 之后 key 是否为 null 不一定 1 当使用new ThreadLocal lt gt set s 定义threadlocal时 没有在栈中声明一个变量指向他 那他就是只被弱引用 在gc后 那这个thre