异步编排

@Configuration
public class MyThreadConfig {
    @Bean
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool) {
        return new ThreadPoolExecutor(
                pool.getCoreSize(),
                pool.getMaxSize(),
                pool.getKeepAliveTime(),
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
    }
}

实现类中注入

@Override
  public OrderConfirmVo confirmOrder() throws ExecutionException, InterruptedException {
    OrderConfirmVo confirmVo = new OrderConfirmVo();
    // 1.查询收获地址
    // 在拦截器中获取memberId 拦截器能到达这里里面携带了id
    MemberRespVo memberRespVo = LoginUserInterceptor.loginUser.get();
    System.out.println("主线程..." + Thread.currentThread().getId());

    CompletableFuture<Void> getAdderssFuture =
        CompletableFuture.runAsync(
            () -> {
              System.out.println("副线程..." + Thread.currentThread().getId());
              // 查询地址
              List<MemberAddressVo> address = memberFeignService.getAddress(memberRespVo.getId());
              confirmVo.setAddress(address);
            },
            executor);

    CompletableFuture<Void> getCartFuture =
        CompletableFuture.runAsync(
            () -> {
              System.out.println("副线程..." + Thread.currentThread().getId());
              // 查询购物车所有选中的购物项
              List<OrderItemVo> items = cartFeginService.getCurrentUserCartItems();
              confirmVo.setItems(items);
            },
            executor);

    // 查询积分
    Integer integration = memberRespVo.getIntegration();
    confirmVo.setIntegration(integration);
    CompletableFuture.allOf(getAdderssFuture, getCartFuture).get();
    return confirmVo;
  }

问题

  • 开启异步线程 请求头信息丢失 查不到信息都为空

Snipaste_2020-11-05_22-41-16

  • 分析原因给相应地方加上线程打印
System.out.println("副线程..." + Thread.currentThread().getId());
  • 控制台结果 和主线程不在一个id上 所以拦截器不会共享数据 Snipaste_2020-11-05_22-38-09
  • 原因 Snipaste_2020-11-05_22-45-17

解决办法

  • 在执行异步任务之前把RequestContextHolder放进去请求共享数据,每一个线程都来共享之前的数据
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
    CompletableFuture<Void> getAdderssFuture =CompletableFuture.runAsync(
    () -> {
     System.out.println("副线程..." + Thread.currentThread().getId());
// 放入请求RequestContextHolder
    RequestContextHolder.setRequestAttributes(requestAttributes);
     List<MemberAddressVo> address = memberFeignService.getAddress(memberRespVo.getId());
              confirmVo.setAddress(address);
            },
            executor);
  • 重启服务之后 vo里就有数据了 Snipaste_2020-11-05_22-53-49