容器启动时,将缓存加载到类的静态属性

该博客讨论了一个Java应用程序在启动时如何初始化静态缓存,包括表格类型、协调制度编码、原产国关系和包装种类等数据。使用StringRedisTemplate从Redis获取并解析数据填充到内存中的Map。文章指出了这种缓存策略的缺点,即需要维护本地缓存且数据存储在元空间,可能需要关注JVM的元空间设置。作者提供了元空间大小调整的建议,并提到了Lucene库的API用于计算对象占用的内存空间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码实现:

@Data
public class HkBaseCache {

    /**
     * 表格类型List
     */
    public static List<BaseCustomsClearanceParameters> tableTypeList = new ArrayList<>();
    /**
     * 协调制度编码Map   key:协调制度编号   value:协调制度对象
     */
    public static  Map<String, BaseHarmonizedSystem> harmonizedMap = new ConcurrentHashMap<>();
    /**
     * 原产国与香港来源国关系Map  key:原产国代码 value:原产国与香港来源国关系
     */
    public static  Map<String, CountryTurnRelation> countryTurnRelationMap = new ConcurrentHashMap<>();
    /**
     * 包装种类Map  key:包装种类代码 value:包装种类信息
     */
    public static  Map<String, BaseCustomsClearanceParameters> packTypeMap = new HashMap<>();

    /**
     * 初始化
     *
     * @param  stringRedisTemplate string序列化的
     * @author  wrx
     * @date  2021/12/25 11:00
     */
    public static HkBaseCache init(StringRedisTemplate stringRedisTemplate){
        HkBaseCache hkBaseCache = new HkBaseCache();
        hkBaseCache.loadCache(stringRedisTemplate);
        return hkBaseCache;
    }

    /**
     * 加载缓存
     *
     * @param  stringRedisTemplate string序列化的
     * @author  wrx
     * @date  2021/12/25 11:00
     */
    private void loadCache(StringRedisTemplate stringRedisTemplate){
        // 设置缓存中的表格类型
        String tableTypeJson = stringRedisTemplate.opsForValue().get(RedisConstants.TZ_REDIS_BASE_CUSTOMS_CLEARANCE_PARAMETERS + BaseCustomsClearanceParametersEnum.TABLE_TYPE.getCode());
        tableTypeList.clear();
        tableTypeList = JSONUtil.toList(JSONUtil.parseArray(tableTypeJson), BaseCustomsClearanceParameters.class);
        // 设置缓存中的协调制度编号
        harmonizedMap.clear();
        Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries(RedisConstants.TZ_REDIS_BASE_HARMONIZED_SYSTEM);
        entries.entrySet().parallelStream().forEach(entry-> harmonizedMap.put(StrUtil.toString(entry.getKey()),JSONUtil.toBean(StrUtil.toString(entry.getValue()),BaseHarmonizedSystem.class)));
        // 设置缓存中的原产国关系
        countryTurnRelationMap.clear();
        Map<Object, Object> entries2 = stringRedisTemplate.opsForHash().entries(RedisConstants.TZ_REDIS_COUNTRY_TURN_RELATION);
        entries2.entrySet().parallelStream().forEach(entry-> countryTurnRelationMap.put(StrUtil.toString(entry.getKey()),JSONUtil.toBean(StrUtil.toString(entry.getValue()),CountryTurnRelation.class)));
        // 设置缓存中的包装种类
        packTypeMap.clear();
        String packTypeJson = stringRedisTemplate.opsForValue().get(RedisConstants.TZ_REDIS_BASE_CUSTOMS_CLEARANCE_PARAMETERS + BaseCustomsClearanceParametersEnum.PACK_TYPE.getCode());
        List<BaseCustomsClearanceParameters> packTypeList = JSONUtil.toList(JSONUtil.parseArray(packTypeJson), BaseCustomsClearanceParameters.class);
        packTypeMap = packTypeList.stream().collect(Collectors.toMap(BaseCustomsClearanceParameters::getCode, obj -> obj));
    }
  • 容器启动时,初始化
@SpringCloudApplication
@Slf4j
public class XXXApplication  implements CommandLineRunner {

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    public static void main(String[] args) {
        SpringApplication.run(XXXApplication.class,args);
    }

    @Override
    public void run(String... args) throws Exception {
        log.info("---------初始化工作 start----------");
        stringRedisTemplate.init();
        log.info("---------初始化工作 end----------");
    }
}

缺点:

  • 需要维护本地缓存,所以本地缓存的数据尽量是恒古不变的
  • 数据存储在元空间,注意自己的JVM设置是否合理

关于元空间的JVM参数有两个:-XX:MetaspaceSize=N和 -XX:MaxMetaspaceSize=N,对于64位JVM来说,元空间的默认初始大小是21MB,默认的元空间的最大值是无限。
-XX:MaxMetaspaceSize: 设置元空间最大值, 默认是-1, 即不限制, 或者说只受限于本地内存大小。
-XX:MetaspaceSize: 指定元空间的初始空间大小, 以字节为单位,默认是21M,达到该值就会触发full gc进行类型卸载, 同时收集器会对该值进行调整: 如果释放了大量的空间, 就适当降低该值; 如果释放了很少的空间, 那么在不超过-XX:MaxMetaspaceSize(如果设置了的话) 的情况下, 适当提高该值。
由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动的时候发生大量Full GC,通常都是由于永久代或元空间发生了大小调整,基于这种情况,一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置得比初始值要大,对于8G物理内存的机器来说,一般我会将这两个值都设置为256M。

如何判断对象占用的空间?

  • pom依赖
<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-core</artifactId>
    <version>8.3.0</version>
</dependency>
  • 调用api计算
long byteCount = RamUsageEstimator.shallowSizeOf(obj);

得到的是字节数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值