From 927cbc705a66aff0f35c57a2fb48187c4a7ce4ed Mon Sep 17 00:00:00 2001 From: "le.kuang" <1741461577@qq.com> Date: Mon, 6 Feb 2023 11:16:37 +0800 Subject: [PATCH] Optimize ConcurrentHashMap#computeIfAbsent have performance problem in jdk1.8 --- .../austin/support/utils/AccountUtils.java | 11 ++--- .../support/utils/ConcurrentHashMapUtils.java | 41 +++++++++++++++++++ 2 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 austin-support/src/main/java/com/java3y/austin/support/utils/ConcurrentHashMapUtils.java diff --git a/austin-support/src/main/java/com/java3y/austin/support/utils/AccountUtils.java b/austin-support/src/main/java/com/java3y/austin/support/utils/AccountUtils.java index cf616f6..10699f4 100644 --- a/austin-support/src/main/java/com/java3y/austin/support/utils/AccountUtils.java +++ b/austin-support/src/main/java/com/java3y/austin/support/utils/AccountUtils.java @@ -24,9 +24,9 @@ import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.core.StringRedisTemplate; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; /** * 获取账号信息工具类 @@ -45,8 +45,8 @@ public class AccountUtils { /** * 消息的小程序/微信服务号账号 */ - private Map officialAccountServiceMap = new ConcurrentHashMap<>(); - private Map miniProgramServiceMap = new ConcurrentHashMap<>(); + private ConcurrentMap officialAccountServiceMap = new ConcurrentHashMap<>(); + private ConcurrentMap miniProgramServiceMap = new ConcurrentHashMap<>(); @Bean public RedisTemplateWxRedisOps redisTemplateWxRedisOps() { @@ -63,15 +63,16 @@ public class AccountUtils { * @param * @return */ + @SuppressWarnings("unchecked") public T getAccountById(Integer sendAccountId, Class clazz) { try { Optional optionalChannelAccount = channelAccountDao.findById(Long.valueOf(sendAccountId)); if (optionalChannelAccount.isPresent()) { ChannelAccount channelAccount = optionalChannelAccount.get(); if (clazz.equals(WxMaService.class)) { - return (T) miniProgramServiceMap.computeIfAbsent(channelAccount, account -> initMiniProgramService(JSON.parseObject(account.getAccountConfig(), WeChatMiniProgramAccount.class))); + return (T)ConcurrentHashMapUtils.computeIfAbsent(miniProgramServiceMap, channelAccount, account -> initMiniProgramService(JSON.parseObject(account.getAccountConfig(), WeChatMiniProgramAccount.class))); } else if (clazz.equals(WxMpService.class)) { - return (T) officialAccountServiceMap.computeIfAbsent(channelAccount, account -> initOfficialAccountService(JSON.parseObject(account.getAccountConfig(), WeChatOfficialAccount.class))); + return (T)ConcurrentHashMapUtils.computeIfAbsent(officialAccountServiceMap, channelAccount, account -> initOfficialAccountService(JSON.parseObject(account.getAccountConfig(), WeChatOfficialAccount.class))); } else { return JSON.parseObject(channelAccount.getAccountConfig(), clazz); } diff --git a/austin-support/src/main/java/com/java3y/austin/support/utils/ConcurrentHashMapUtils.java b/austin-support/src/main/java/com/java3y/austin/support/utils/ConcurrentHashMapUtils.java new file mode 100644 index 0000000..f4bd3ac --- /dev/null +++ b/austin-support/src/main/java/com/java3y/austin/support/utils/ConcurrentHashMapUtils.java @@ -0,0 +1,41 @@ +package com.java3y.austin.support.utils; + +import java.util.concurrent.ConcurrentMap; +import java.util.function.Function; + +/** + * @author kl + * @version 1.0.0 + * @description ConcurrentHashMap util + * @date 2023/2/6 10:01 + */ +public class ConcurrentHashMapUtils { + + private static boolean IS_JAVA8; + + static { + try { + IS_JAVA8 = System.getProperty("java.version").startsWith("1.8."); + } catch (Exception ignore) { + // exception is ignored + IS_JAVA8 = true; + } + } + + /** + * Java 8 ConcurrentHashMap#computeIfAbsent 存在性能问题的临时解决方案 + * @see https://bugs.openjdk.java.net/browse/JDK-8161372 + * + */ + public static V computeIfAbsent(ConcurrentMap map, K key, Function func) { + if (IS_JAVA8) { + V v = map.get(key); + if (null == v) { + v = map.computeIfAbsent(key, func); + } + return v; + } else { + return map.computeIfAbsent(key, func); + } + } +}