mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
修复MapUtil.computeIfAbsent可能存在的并发问题
This commit is contained in:
@@ -9,6 +9,7 @@ import cn.hutool.core.lang.Pair;
|
||||
import cn.hutool.core.lang.TypeReference;
|
||||
import cn.hutool.core.stream.CollectorUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.JdkUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
@@ -1459,30 +1460,35 @@ public class MapUtil {
|
||||
*/
|
||||
public static <K, V> Map.Entry<K, V> entry(K key, V value, boolean isImmutable) {
|
||||
return isImmutable ?
|
||||
new AbstractMap.SimpleImmutableEntry<>(key, value) :
|
||||
new AbstractMap.SimpleEntry<>(key, value);
|
||||
new AbstractMap.SimpleImmutableEntry<>(key, value) :
|
||||
new AbstractMap.SimpleEntry<>(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果 key 对应的 value 不存在,则使用获取 mappingFunction 重新计算后的值,并保存为该 key 的 value,否则返回 value。<br>
|
||||
* 方法来自Dubbo,解决使用ConcurrentHashMap.computeIfAbsent导致的死循环问题。(issues#2349)<br>
|
||||
* A temporary workaround for Java 8 specific performance issue JDK-8161372 .<br>
|
||||
* This class should be removed once we drop Java 8 support.
|
||||
* This class should be removed once we drop Java 8 support.<br>
|
||||
* 参考:https://github.com/apache/dubbo/blob/3.2/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConcurrentHashMapUtils.java
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @param map Map
|
||||
* @param key 键
|
||||
* @param mappingFunction 值不存在时值的生成函数
|
||||
* @see <a href="https://bugs.openjdk.java.net/browse/JDK-8161372">https://bugs.openjdk.java.net/browse/JDK-8161372</a>
|
||||
* @return 值
|
||||
* @see <a href="https://bugs.openjdk.java.net/browse/JDK-8161372">https://bugs.openjdk.java.net/browse/JDK-8161372</a>
|
||||
*/
|
||||
public static <K, V> V computeIfAbsent(Map<K, V> map, K key, Function<? super K, ? extends V> mappingFunction) {
|
||||
V value = map.get(key);
|
||||
if (null == value) {
|
||||
map.putIfAbsent(key, mappingFunction.apply(key));
|
||||
value = map.get(key);
|
||||
if (JdkUtil.IS_JDK8) {
|
||||
V value = map.get(key);
|
||||
if (null == value) {
|
||||
//map.putIfAbsent(key, mappingFunction.apply(key));
|
||||
value = map.computeIfAbsent(key, mappingFunction);
|
||||
}
|
||||
return value;
|
||||
} else {
|
||||
return map.computeIfAbsent(key, mappingFunction);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
86
hutool-core/src/main/java/cn/hutool/core/util/JdkUtil.java
Normal file
86
hutool-core/src/main/java/cn/hutool/core/util/JdkUtil.java
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2023 looly(loolly@aliyun.com)
|
||||
* Hutool is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package cn.hutool.core.util;
|
||||
|
||||
/**
|
||||
* JDK相关工具类,包括判断JDK版本等<br>
|
||||
* 工具部分方法来自fastjson2的JDKUtils
|
||||
*
|
||||
* @author fastjson, looly
|
||||
*/
|
||||
public class JdkUtil {
|
||||
/**
|
||||
* JDK版本
|
||||
*/
|
||||
public static final int JVM_VERSION;
|
||||
/**
|
||||
* 是否JDK8<br>
|
||||
* 由于Hutool基于JDK8编译,当使用JDK版本低于8时,不支持。
|
||||
*/
|
||||
public static final boolean IS_JDK8;
|
||||
/**
|
||||
* 是否大于等于JDK17
|
||||
*/
|
||||
public static final boolean IS_AT_LEAST_JDK17;
|
||||
|
||||
/**
|
||||
* 是否Android环境
|
||||
*/
|
||||
public static final boolean IS_ANDROID;
|
||||
|
||||
static {
|
||||
// JVM版本
|
||||
JVM_VERSION = _getJvmVersion();
|
||||
IS_JDK8 = 8 == JVM_VERSION;
|
||||
IS_AT_LEAST_JDK17 = JVM_VERSION >= 17;
|
||||
|
||||
// JVM名称
|
||||
final String jvmName = _getJvmName();
|
||||
IS_ANDROID = jvmName.equals("Dalvik");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取JVM名称
|
||||
*
|
||||
* @return JVM名称
|
||||
*/
|
||||
private static String _getJvmName() {
|
||||
return System.getProperty("java.vm.name");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据{@code java.specification.version}属性值,获取版本号
|
||||
*
|
||||
* @return 版本号
|
||||
*/
|
||||
private static int _getJvmVersion() {
|
||||
int jvmVersion = -1;
|
||||
|
||||
try{
|
||||
String javaSpecVer = System.getProperty("java.specification.version");
|
||||
if (StrUtil.isNotBlank(javaSpecVer)) {
|
||||
if (javaSpecVer.startsWith("1.")) {
|
||||
javaSpecVer = javaSpecVer.substring(2);
|
||||
}
|
||||
if (javaSpecVer.indexOf('.') == -1) {
|
||||
jvmVersion = Integer.parseInt(javaSpecVer);
|
||||
}
|
||||
}
|
||||
} catch (Throwable ignore){
|
||||
// 默认JDK8
|
||||
jvmVersion = 8;
|
||||
}
|
||||
|
||||
return jvmVersion;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user