Java线程及线程池的相关的问题

1、线程池有哪些状态

线程池在Java中有五种状态:

RUNNING(运行状态)线程创建后默认进入此状态,能够接受新任务并处理任务队列中的任务。如果不调用关闭方法,线程池会一直保持此状态。

SHUTDOWN(关闭状态) 调用shutdown()方法后进入此状态。现成池不再接受新任务,但会继续处理任务队列中的任务,直到到全部完成。

STOP(停止状态)调用shutdownNow()方法后进入此状态。线程池不再接受新任务,同时会中断正在执行的任务,并放弃任务队列中的任务。

TIDYING(整理状态)当所有任务(包括任务队列中的任务)都执行完毕,且活动线程数降为0时,现成池进入此状态。在此状态下会调用terminated()方法。

TERMINATED(销毁状态)线程池在执行完terminated()方法后进入此状态,表示线程池完全关闭。

2、线程有哪些状态

线程在Java中有六种状态:

NEW(初始状态) 当一个线程对象被创建但尚未调用start()方法时,它处于初始状态。

RUNNABLE(运行状态)线程调用start()方法后进入就绪状态,等待CPU调度,当获得CPU时间片后,进入运行中状态。运行状态还包括就绪(ready)和运行中(running)两种状态。

BLOCKED(阻塞状态) 当现成视图进入一个被其他线程占用的同步代码块或方法时,它进入阻塞状态,等待锁的释放。

WAITING(等待状态) 线程进入等待黄铜,需要 等待其他线程显式唤醒。调用Object.wait()、Thread.join()或者LockSupport.park()方法会使线程进入等待状态。

TIMED_WAITING(超时等待状态)调用Thread.sleep(1000),Object.wait(1000)等方法会使线程进入超时等待状态。

TERMINATED(终止状态)当任务执行完毕后就进入终止状态

3、ThradLocalMap中的key为何要设计成弱引用

Sun 公司(现 Oracle)在 JDK 源码中将 ThreadLocalMap 的 Key(即 ThreadLocal 实例)设计为弱引用,主要是出于防御性设计的考虑,旨在解决在特定场景下(尤其是线程池)极易发生的 Key 内存泄漏问题。

具体原因可以从以下两个维度的对比来理解:

  1. 假设 Key 使用强引用(会导致 Key 泄漏)

如果 ThreadLocalMap 内部的 Entry 对 ThreadLocal 实例持有强引用,当我们在业务代码中不再需要该 ThreadLocal 变量,并将其置为 null 时,由于当前线程(如线程池中的核心线程)依然存活,ThreadLocalMap 依然持有该 Entry。

此时,Entry 强引用着 ThreadLocal 实例,导致垃圾回收器(GC)无法回收它。只要线程不结束,这个 ThreadLocal 对象就会一直驻留在堆内存中,造成严重的内存泄漏。

  1. 采用弱引用(JDK 设计者的"妥协"与"智慧")

为了打破上述强引用链,JDK 引入了弱引用(WeakReference)机制:

弱引用的特性:只具有弱引用的对象,在下一次 GC 发生时,无论当前内存空间是否充足,都会被直接回收。

设计效果:当外部业务代码不再持有 ThreadLocal 的强引用时,ThreadLocalMap 中的 Key 会在 GC 时被自动回收,变成 null。这从根本上保证了 ThreadLocal 对象本身能够被及时回收,避免了 Key 层的内存泄漏。

4、线程池如何预热核心线程

可以使用ThreadPoolExecutor的prestartCoreThread或prestartAllCoreThreads方法预热核心线程。这样

线程池默认是惰性创建线程的,在需要及时响应的场景下提前预热可加快任务的处理,从而缩短响应时间。

5、如果需要将100个元素一次性高效写入HashMap中,该如何做

HashMap默认的初始化容量是16,扩容因子是0.75,扩容数是2的幂次,要使HashMap初始化后可以容纳100个元素不进行扩容,需在创建HashMap中将初始化容量设计为100/0.75+1,或者直接写256,因为HashMap底层会将129-255之间的数字改写为256

6、MVCC是什么,在哪里用到

MVCC(Multi-Version Concurrency Control)是多版本并发控制的英文简写,是一种用于提高数据库并发性能的机制,通过维护数据的多个版本来实现事物的隔离性,允许读写操作同时进行,从而提高数据库的并发性能和响应能力。

MVCC的基本原理

MVCC通过为每行数据维护多个版本来工作,每个版本都有自己的创建时间和事务ID。当一个事务需要读取数据时,它会读取对应版本的数据,而不是最新的数据。MVCC避免了使用传统的锁机制来管理数据的并发访问,减少了锁竞争,从而提升了系统的吞吐量和响应时间。

MVCC的实现基于undolog版本链readview

隐式字段

在MySQL存储的数据中,除了显式定义的字段,MySQL会隐含地定义几个字段:

trx_id:事务ID,每进行一次事务操作,就会自增1。

roll_pointer:回滚指针,用于找到上一个版本的数据,结合undolog进行回滚。

ReadView

ReadView是事务进行快照读操作时生成的读视图,用于判断版本链中的哪个版本对当前事务是可见的。在RC隔离级别下,每个快照读都会生成并获取最新的ReadView;在RR隔离级别下,只有在同一个事务的第一个快照读才会创建ReadView,之后的每次快照读都使用同一个ReadView。

版本链

对于每次更新操作,旧值会被保存到一条undolog中,形成版本链。版本链的头节点代表当前记录的最新值,每个版本还包含生成该版本的事务ID。

7、有哪些容器是并发安全的

Vector java 1.0中加入的线程安全的动态数组,性能低

Hashtable java早期的map,性能低

ConcurrentHashMap,HashMap的线程安全版

CopyOnWriteArrayList,ArrayList的线程安全版

ConcurrentLinkedQueue,LinkedList的线程安全版

BlockingQueue,阻塞队列

ConcurrentSkipListMap,TreeMao的线程安全版

相关推荐
wb043072011 小时前
外卖大战——从阿明的“3 秒生死线“,看系统性能优化的全链路方法论
开发语言·性能优化·架构·php
爱吃羊的老虎1 小时前
【JAVA】Java微服务—网关Gateway
java·微服务·gateway
CTA终结者1 小时前
Python 写期货自动交易:行情下单与成交回报怎么组织
开发语言·python·区块链
TE-茶叶蛋1 小时前
Next.js中App Router 全部特殊文件一览
开发语言·javascript·网络
红藕香残玉簟秋1 小时前
【Rust学习】windows安装rust
开发语言·学习·rust
弹简特2 小时前
【零基础学Python】08-Python面向对象之封装、多态和函数进阶
开发语言·python
人道领域2 小时前
一篇文章解决Codex的安装,实操一遍过
java·开发语言·codex
thisiszdy2 小时前
<C++> 智能指针
开发语言·c++
fox_lht2 小时前
第十四章 一个输入和输出项目:构建一个命令行程序
开发语言·后端·rust