【发布时间】:2020-01-05 00:47:31
【问题描述】:
自 2019 年 8 月 21 日起提供的 Sonar 规则 (squid:S5164 / RSPEC-5164) 要求在不再使用时清理“ThreadLocal”变量。所以,让我们采用以下类(JDK6兼容):
public class ThreadLocalExample {
private static final ThreadLocal<NumberFormat> formats = new ThreadLocal<NumberFormat>() {
@Override
protected NumberFormat initialValue() {
final NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(2);
nf.setGroupingUsed(false);
return nf;
}
};
public static NumberFormat getFormatter() {
return formats.get();
}
}
Sonar 在ThreadLocal 声明中报告了一个主要错误,解释如下:
“ThreadLocal”变量不再使用时应清理
ThreadLocal变量应该被垃圾回收一次 持有线程不再活着。持有时可能会发生内存泄漏 线程被重用,这在应用程序服务器上使用 线程池。为避免此类问题,建议经常清理
ThreadLocal变量使用remove()方法删除当前ThreadLocal变量的线程值。
现在,我采用ThreadLocal 方法是为了尽可能重用NumberFormat 实例,避免每次调用创建一个实例,所以我想如果我在代码中的某处调用remove(),我会失去此解决方案的所有优势。我错过了什么吗?非常感谢。
【问题讨论】:
-
您是否真正分析过使用
ThreadLocal和简单地创建一个新实例并在每次调用getFormatter时返回它之间是否存在差异?如果您要这样做,那么推理实例的生命周期似乎要容易得多。
标签: java memory-leaks sonarqube number-formatting thread-local