当前位置: 代码迷 >> 综合 >> Java 多线程的正确使用姿势
  详细解决方案

Java 多线程的正确使用姿势

热度:82   发布时间:2024-01-25 10:29:01.0

昨天线上的导出文件数据出现了问题(导出的数据= A表通过sql查出来+B表通过异步接口查询出来数据拼装),经过排查是由于我使用了Spring core包中的ThreadPoolTaskExecutor类去异步获取另一个B表中的数据,B表中的数据还没有完全返回回来。接口就已经返回了,所以导致导出数据问题。

然后换成了Futrue后,问题解决,如下:

private final ExecutorService es = new ThreadPoolExecutor(8, 10, 100, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(5000));        List<TruckBrokerOrderDto> orderDtoList = new ArrayList<>();List<order> orderList = orderService.selectOrderList(query);Map<String, Future<orderDto>> futureMap = new HashMap<>();for (Order order : orderList) {Future<OrderDto> orderFuture = es.submit(new Callable<OrderDto>() {@Overridepublic OrderDto call() {OrderDto orderAmountDto = new OrderDto();// 查计划信息AmountQuery amountQuery = new AmountQuery();amountQuery.setOrderId(order.getOrderId());amountQuery.setOrderCode(order.getOrderCode());List<Amount> amountList = amountService.selectAmountList(amountQuery);if (amountList != null && amountList.size() > 0) {//  数据处理}return orderAmountDto;}});futureMap.put(order.getOrderCode(), orderFuture);}for (Order order  : orderList) {OrderDto orderDto = new OrderDto();BeanUtils.copyProperties(brokerOrder, orderDto);try {TruckBrokerOrderDto orderAmountDto = futureMap.get(brokerOrder.getTruckBrokerOrderCode()).get();if (orderAmountDto.getDriverAmountList() != null && orderAmountDto.getDriverAmountList().size() > 0) {orderDto.setDriverAmountList(orderAmountDto.getDriverAmountList());}if (orderAmountDto.getAmountList() != null && orderAmountDto.getAmountList().size() > 0) {orderDto.setAmountList(orderAmountDto.getAmountList());}} catch (Exception e) {LOG.info("error " ,e);}orderDtoList.add(orderDto);}int count = OrderService.selectOrderListCount(query);returnReturn.create(new Result<OrderDto>(count, orderDtoList));

总结:

一般不需要对异步返回数据做处理的话,可以直接用Spring core包中的ThreadPoolTaskExecutor类直接执行(会丢失数据),比如发送短信,异步更新数据不需要返回结果等。

假如要对异步返回数据做处理的话,请用多线程的Futrue模式,可以保证数据不丢失。