mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
修复MapUtil.computeIfAbsent可能存在的并发问题
This commit is contained in:
parent
8420a9b0a1
commit
4bc25e92d8
@ -11,10 +11,12 @@
|
||||
* 【core 】 NumberUtil增加(pr#968@Gitee)
|
||||
* 【core 】 Number128增加hash和equals方法(pr#968@Gitee)
|
||||
* 【core 】 NamingCase.toCamelCase新增重载,可选是否转换其他字符为小写(issue#3031@ithub)
|
||||
* 【core 】 新增JdkUtil
|
||||
|
||||
### 🐞Bug修复
|
||||
* 【core 】 CollUtil.split优化切割列表参数判断,避免OOM(pr#3026@Github)
|
||||
* 【core 】 修复FileUtil.move传入相同目录或子目录丢失源目录的问题(pr#3032@Github)
|
||||
* 【core 】 修复MapUtil.computeIfAbsent可能存在的并发问题(issue#I6RVMY@Gitee)
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
# 5.8.16 (2023-03-26)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package cn.hutool.http.ssl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.JdkUtil;
|
||||
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
@ -22,7 +22,7 @@ public class DefaultSSLInfo {
|
||||
|
||||
static {
|
||||
TRUST_ANY_HOSTNAME_VERIFIER = new TrustAnyHostnameVerifier();
|
||||
if (StrUtil.equalsIgnoreCase("dalvik", System.getProperty("java.vm.name"))) {
|
||||
if (JdkUtil.IS_ANDROID) {
|
||||
// 兼容android低版本SSL连接
|
||||
DEFAULT_SSF = new AndroidSupportSSLFactory();
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user