mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
修复ConcurrentHashMap.computeIfAbsent缺陷导致的问题
This commit is contained in:
parent
3fd1ebe0f5
commit
920fe44e50
@ -18,6 +18,7 @@
|
|||||||
* 【db 】 修复Hive2驱动无法识别问题(issue#2606@Github)
|
* 【db 】 修复Hive2驱动无法识别问题(issue#2606@Github)
|
||||||
* 【core 】 修复computeIfAbsent问题(issue#I5PTN3@Gitee)
|
* 【core 】 修复computeIfAbsent问题(issue#I5PTN3@Gitee)
|
||||||
* 【extra 】 修复Ftp中路径问题(issue#I5R2DE@Gitee)
|
* 【extra 】 修复Ftp中路径问题(issue#I5R2DE@Gitee)
|
||||||
|
* 【core 】 修复ConcurrentHashMap.computeIfAbsent缺陷导致的问题
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package cn.hutool.core.bean;
|
package cn.hutool.core.bean;
|
||||||
|
|
||||||
import cn.hutool.core.lang.func.Func0;
|
import cn.hutool.core.lang.func.Func0;
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.map.WeakConcurrentMap;
|
import cn.hutool.core.map.WeakConcurrentMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,7 +24,7 @@ public enum BeanDescCache {
|
|||||||
* @since 5.4.2
|
* @since 5.4.2
|
||||||
*/
|
*/
|
||||||
public BeanDesc getBeanDesc(Class<?> beanClass, Func0<BeanDesc> supplier) {
|
public BeanDesc getBeanDesc(Class<?> beanClass, Func0<BeanDesc> supplier) {
|
||||||
return bdCache.computeIfAbsent(beanClass, (key)->supplier.callWithRuntimeException());
|
return MapUtil.computeIfAbsent(bdCache, beanClass, (key)->supplier.callWithRuntimeException());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package cn.hutool.core.lang;
|
package cn.hutool.core.lang;
|
||||||
|
|
||||||
import cn.hutool.core.lang.func.Func0;
|
import cn.hutool.core.lang.func.Func0;
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import cn.hutool.core.util.ClassUtil;
|
import cn.hutool.core.util.ClassUtil;
|
||||||
import cn.hutool.core.util.ReflectUtil;
|
import cn.hutool.core.util.ReflectUtil;
|
||||||
@ -52,15 +53,7 @@ public final class Singleton {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T> T get(String key, Func0<T> supplier) {
|
public static <T> T get(String key, Func0<T> supplier) {
|
||||||
//return (T) POOL.computeIfAbsent(key, (k)-> supplier.callWithRuntimeException());
|
return (T) MapUtil.computeIfAbsent(POOL, key, (k)-> supplier.callWithRuntimeException());
|
||||||
// issues#2349
|
|
||||||
// ConcurrentHashMap.computeIfAbsent在某些情况下会导致死循环问题,此处采用Dubbo的解决方案
|
|
||||||
Object value = POOL.get(key);
|
|
||||||
if(null == value){
|
|
||||||
POOL.putIfAbsent(key, supplier.callWithRuntimeException());
|
|
||||||
value = POOL.get(key);
|
|
||||||
}
|
|
||||||
return (T) value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1464,17 +1464,19 @@ public class MapUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 方法来自MyBatis,解决使用ConcurrentHashMap.computeIfAbsent导致的死循环问题。<br>
|
* 方法来自Dubbo,解决使用ConcurrentHashMap.computeIfAbsent导致的死循环问题。<br>
|
||||||
|
* issues#2349<br>
|
||||||
* A temporary workaround for Java 8 specific performance issue JDK-8161372 .<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.
|
||||||
*
|
*
|
||||||
* @see <a href="https://bugs.openjdk.java.net/browse/JDK-8161372">https://bugs.openjdk.java.net/browse/JDK-8161372</a>
|
* @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<K, V> mappingFunction) {
|
public static <K, V> V computeIfAbsent(Map<K, V> map, K key, Function<K, V> mappingFunction) {
|
||||||
final V value = map.get(key);
|
V value = map.get(key);
|
||||||
if (value != null) {
|
if(null == value){
|
||||||
|
map.putIfAbsent(key, mappingFunction.apply(key));
|
||||||
|
value = map.get(key);
|
||||||
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
return map.computeIfAbsent(key, mappingFunction);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import cn.hutool.core.exceptions.UtilException;
|
|||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.lang.JarClassLoader;
|
import cn.hutool.core.lang.JarClassLoader;
|
||||||
import cn.hutool.core.lang.Pair;
|
import cn.hutool.core.lang.Pair;
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.map.WeakConcurrentMap;
|
import cn.hutool.core.map.WeakConcurrentMap;
|
||||||
import cn.hutool.core.text.CharPool;
|
import cn.hutool.core.text.CharPool;
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ public class ClassLoaderUtil {
|
|||||||
* 原始类型名和其class对应表,例如:int =》 int.class
|
* 原始类型名和其class对应表,例如:int =》 int.class
|
||||||
*/
|
*/
|
||||||
private static final Map<String, Class<?>> PRIMITIVE_TYPE_NAME_MAP = new ConcurrentHashMap<>(32);
|
private static final Map<String, Class<?>> PRIMITIVE_TYPE_NAME_MAP = new ConcurrentHashMap<>(32);
|
||||||
private static final WeakConcurrentMap<Pair<String, ClassLoader>, Class<?>> CLASS_CACHE = new WeakConcurrentMap<>();
|
private static final Map<Pair<String, ClassLoader>, Class<?>> CLASS_CACHE = new WeakConcurrentMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
List<Class<?>> primitiveTypes = new ArrayList<>(32);
|
List<Class<?>> primitiveTypes = new ArrayList<>(32);
|
||||||
@ -199,7 +200,7 @@ public class ClassLoaderUtil {
|
|||||||
if (clazz == null) {
|
if (clazz == null) {
|
||||||
final String finalName = name;
|
final String finalName = name;
|
||||||
final ClassLoader finalClassLoader = classLoader;
|
final ClassLoader finalClassLoader = classLoader;
|
||||||
clazz = CLASS_CACHE.computeIfAbsent(Pair.of(name, classLoader), (key)-> doLoadClass(finalName, finalClassLoader, isInitialized));
|
clazz = MapUtil.computeIfAbsent(CLASS_CACHE, Pair.of(name, classLoader), (key)-> doLoadClass(finalName, finalClassLoader, isInitialized));
|
||||||
}
|
}
|
||||||
return clazz;
|
return clazz;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user