1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-06-16 18:10:13 +08:00

Compare commits

...

6 Commits

Author SHA1 Message Date
Guide
dcc302dcc8
Merge pull request #2589 from Listen-to-the-mountains-and-seas/main
修正ThreadLocal造成内存泄漏的描述
2025-01-26 21:39:39 +08:00
Guide
026ebaf5cf
Merge pull request #2590 from flying-pig-z/main
fix:修改语句中词语重复
2025-01-26 21:38:11 +08:00
Guide
b98ef11521
Merge pull request #2591 from pykeeee/patch-1
bigDecimal篇修正
2025-01-26 21:37:10 +08:00
pykeeee
98fb76bc59
Update bigdecimal.md
浮点数和小数是不同的概念,这里有些混淆。浮点数是计算机常用的表示小数的方式,而bigDecimal是用来解决二进制浮点数无法精确表示十进制小数的问题。本质上,bigDecimal也是浮点数,只不过是十进制浮点数。
2025-01-26 10:40:43 +08:00
flying pig
80c5cc433d
fix:修改语句中词语重复 2025-01-26 10:09:33 +08:00
26684
a952018fff 修正ThreadLocal造成内存泄漏的描述
- 将"机会造成内存泄漏"修正为"即会造成内存泄漏"
2025-01-25 19:46:18 +08:00
2 changed files with 6 additions and 6 deletions

View File

@ -21,7 +21,7 @@ System.out.println(a == b);// false
**为什么浮点数 `float``double` 运算的时候会有精度丢失的风险呢?**
这个和计算机保存浮点数的机制有很大关系。我们知道计算机是二进制的,而且计算机在表示一个数字时,宽度是有限的,无限循环的小数存储在计算机时,只能被截断,所以就会导致小数精度发生损失的情况。这也就是解释了为什么浮点数没有办法用二进制精确表示。
这个和计算机保存数的机制有很大关系。我们知道计算机是二进制的,而且计算机在表示一个数字时,宽度是有限的,无限循环的小数存储在计算机时,只能被截断,所以就会导致小数精度发生损失的情况。这也就是解释了为什么十进制小数没有办法用二进制精确表示。
就比如说十进制下的 0.2 就没办法精确转换成二进制小数:
@ -40,9 +40,9 @@ System.out.println(a == b);// false
## BigDecimal 介绍
`BigDecimal` 可以实现对浮点数的运算,不会造成精度丢失。
`BigDecimal` 可以实现对数的运算,不会造成精度丢失。
通常情况下,大部分需要浮点数精确运算结果的业务场景(比如涉及到钱的场景)都是通过 `BigDecimal` 来做的。
通常情况下,大部分需要数精确运算结果的业务场景(比如涉及到钱的场景)都是通过 `BigDecimal` 来做的。
《阿里巴巴 Java 开发手册》中提到:**浮点数之间的等值判断,基本数据类型不能用 == 来比较,包装数据类型不能用 equals 来判断。**
@ -50,7 +50,7 @@ System.out.println(a == b);// false
具体原因我们在上面已经详细介绍了,这里就不多提了。
想要解决浮点数运算精度丢失这个问题,可以直接使用 `BigDecimal` 来定义浮点数的值,然后再进行浮点数的运算操作即可。
想要解决浮点数运算精度丢失这个问题,可以直接使用 `BigDecimal` 来定义小数的值,然后再进行小数的运算操作即可。
```java
BigDecimal a = new BigDecimal("1.0");

View File

@ -148,7 +148,7 @@ static class Entry extends WeakReference<ThreadLocal<?>> {
- **key 是弱引用**`ThreadLocalMap` 中的 key 是 `ThreadLocal` 的弱引用 (`WeakReference<ThreadLocal<?>>`)。 这意味着,如果 `ThreadLocal` 实例不再被任何强引用指向,垃圾回收器会在下次 GC 时回收该实例,导致 `ThreadLocalMap` 中对应的 key 变为 `null`
- **value 是强引用**:即使 `key` 被 GC 回收,`value` 仍然被 `ThreadLocalMap.Entry` 强引用存在,无法被 GC 回收。
`ThreadLocal` 实例失去强引用后,其对应的 value 仍然存在于 `ThreadLocalMap` 中,因为 `Entry` 对象强引用了它。如果线程持续存活(例如线程池中的线程),`ThreadLocalMap` 也会一直存在,导致 key 为 `null` 的 entry 无法被垃圾回收,会造成内存泄漏。
`ThreadLocal` 实例失去强引用后,其对应的 value 仍然存在于 `ThreadLocalMap` 中,因为 `Entry` 对象强引用了它。如果线程持续存活(例如线程池中的线程),`ThreadLocalMap` 也会一直存在,导致 key 为 `null` 的 entry 无法被垃圾回收,会造成内存泄漏。
也就是说,内存泄漏的发生需要同时满足两个条件:
@ -464,7 +464,7 @@ public static class CallerRunsPolicy implements RejectedExecutionHandler {
}
```
### 如果不允许丢弃任务任务,应该选择哪个拒绝策略?
### 如果不允许丢弃任务,应该选择哪个拒绝策略?
根据上面对线程池拒绝策略的介绍,相信大家很容易能够得出答案是:`CallerRunsPolicy`