并发线上问题case

case一、并行流向hashmap插入数据
背景:nps服务启动的时候,会并发将策略类注册到静态map集合中
代码:

public class DemoRegistry implements InitializingBean, BeanFactoryAware {
    private static Map<Integer, TestService> registryMap = new HashMap<>(2);
    private BeanFactory beanFactory;

    public static TestService getTestService(Integer index) {
        return registryMap.get(index);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Map<String, TestService> map = ((ListableBeanFactory) beanFactory).getBeansOfType(TestService.class);
        map.values().parallelStream().forEach(it -> registryMap.put(it.demoType().getType(), it));
        String str = String.format("已注册了%s条Demo测试数据. map[ %s ]",map.size(),
                map.entrySet().stream().map(entry -> entry.getValue().demoType().getType().toString())
                        .collect(Collectors.joining(",")));
        System.out.println(str);
    }
} 

解决方案:
1、使用 ConcurrentHashMap
ConcurrentHashMap 是线程安全的实现,它在并发环境下使用分段锁来实现高效的并发访问。
2、使用同步块
你也可以使用同步块来确保 put 操作的线程安全,但这会降低并行性能
3、禁用并行流
如果数据量不大,或者并行并没有明显的性能提升,可以使用普通的流来避免并发问题:

注意:Java 8 中的 parallelStream 是使用自带的线程池来执行并行操作的。
详细解释
在 Java 8 中,parallelStream 通过 ForkJoinPool 来实现并行流的处理。默认情况下,ForkJoinPool中的公共线程池(common pool)用于并行流的任务执行。
ForkJoinPool
ForkJoinPool.commonPool():这是一个公共的、共享的线程池,默认情况下由所有并行流共享使用。
默认线程数:默认情况下,ForkJoinPool.commonPool() 的大小是可用处理器数(CPU 核心数)减去 1。

case二:系统未制定线程池进行异步,使用了功能线程池

private static void problemCode() {
  CompletableFuture<Void> waybillFuture = CompletableFuture.runAsync(() -> {
    //关联运单信息
    initOrderWaybillInfo(wmOrderResult, finalWmOrderDTO);
    //设置站长信息
    initWmOrderHorseMan(wmOrderResult, finalWmOrderDTO);

  });

  CompletableFuture<Void> mealFuture = CompletableFuture.runAsync(() -> {
    try {
      // 商家出餐慢标签和预判责结果
      isPoiMealSlowOutAndPreResponsubleParty(id, finalWmOrderDTO, wmOrderResult);
    } catch (Exception e) {
      LOGGER.error("{} 商家出餐慢标签和预判责结果出现异常", LOG_PREFIX, e);
    }
  });
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值