小工具      在线工具  汉语词典  css  js  c++  java

Java 多线程的正确使用姿势

Java 额外说明

收录于:43天前

昨天网上导出的文件数据出现问题(导出的数据=通过SQL找到A表+通过异步接口查询B表组装数据)。经查,是因为我使用了Spring核心包中的ThreadPoolTask​​Executor类来异步获取的。另一个表B中的数据,表B中的数据还没有完全返回。接口已经返回,导致导出数据出现问题。

1、会丢失导出数据的代码如下:

<!-- 通用异步执行器 -->
	<bean id="taskExecutor"
		  class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
		<property name="corePoolSize" value="10" />
		<property name="maxPoolSize" value="30" />
	</bean>
 @Autowired
    TaskExecutor taskExecutor;

List<OrderDto> orderDtoList = new ArrayList<>();
        List<Order> orderList = OrderService.selectOrderList(query);
        for (Order brokerOrder : orderList) {

            OrderDto orderDto = new OrderDto();
            BeanUtils.copyProperties(brokerOrder, orderDto);
            taskExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 查计划信息
                        AmountQuery amountQuery = new AmountQuery();
                        amountQuery.setOrderId(brokerOrder.getOrderId());
                        amountQuery.setOrderCode(brokerOrder.getOrderCode());
                        Return<Result<AmountDto>> amountList = amountFacadeService.selectOrderPayAmountList(amountQuery);
                        Result pageResult = amountList.R;
                        if (pageResult != null && pageResult.getData() != null && pageResult.getData().size() > 0) {
                            List<AmountDto> alist = new ArrayList<>();
                            List<AmountDto> list = pageResult.getData();
                            for (AmountDto dto : list) {
                                alist.add(dto);
                            }
                            orderDto.setAmountList(alist);
                        }
                    } catch (Exception e) {
                        LOG.info("error ",e);
                    }
                }
            });

            orderDtoList.add(orderDto);
        }

        int count = OrderService.selectOrderListCount(query);
        return Return.create(new Result<OrderDto>(count, orderDtoList));

2.然后切换到多线程Future后,问题就解决了。部分代码如下:

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>() {
                @Override
                public 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 {
                OrderDto orderAmountDto = futureMap.get(order.getOrderCode()).get();
                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核心包中的ThreadPoolTask​​Executor类直接执行(数据会丢失),比如发送短信、异步更新数据而不返回结果, ETC。

如果要处理异步返回的数据,请使用多线程Future模式,保证数据不丢失。

. . .

相关推荐

额外说明

html5-拖放 拖放

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, init

额外说明

mysql 存储引擎 CSV

            CREATE TABLE mycsv (id int not null,c1 VARCHAR(10) not null,c2 VARCHAR(10) not null) ENGINE= csv;  

额外说明

MS Sql Server查询数据库文件大小和剩余空间,并压缩数据库日志

Sql Server查询数据库文件大小和剩余空间,数据库日志压缩 A、磁盘空间的使用情况及各数据库数据文件及日志文件的大小及使用利用率 1、查询各个磁盘分区的剩余空间: 2、查询数据库的数据文件及日志文件的相关信息 3、查询当前数据库的磁盘使用情况: 4

额外说明

leetcode练习14(找到最长的公共字符串)

题目:输出一个字符串数组中所有字符串的最大公共字符串。 题解:简单题,不解释,直接上代码 class solution { private: public: string extract(string obj1, string obj2); s

额外说明

Python 第五节 第三课

[toc] break 语句 break 语句可用于 while 和 for 循环, 用来结束整个循环. 当有嵌套循环时, break 语句只能跳出最近一层的循环. continue  语句 countinue 语句用于结束本次循环, 继续下一次. 多个

额外说明

【Unity3D日常开发】生成预制体,并且预制体自动销毁

推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 QQ群:1040082875 一、前言 今天有粉丝问我一个很简单的问题,如何生成预制体,并且让预制体自动销毁。 这对老鸟来说应该是很简单的,但是对于新学习Uni

额外说明

nginx 负载均衡配置

前言 nginx作为一款企业级的代理服务器,不管是大中小各类生产项目中,均有广泛的使用,尤其是在前后端分离的项目中,nginx作为路由转发的功能是非常常用的; 在一些流量比较大的项目中,为了应对高并发的场景,后端服务往往采用集群部署,这时候,就需要使用到

额外说明

函数式接口:Java 中的函数式编程利器

文章目录 1. 函数式接口概念 2. 注解 3. 自定义函数式接口 4. 函数式编程 4.1 Lambda的延迟执行效果 4.2 使用Lambda作为参数和返回值 作为参数使用 作为返回值使用 5. 常用的函数接口 5.1 `Supplier`:生产者

额外说明

使用前缀和写的题

P3131 [USACO16JAN]Subsequences Summing to Sevens S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)  ⭐⭐⭐ 当s[r]和s[l−1]模7相同时,区间就能被7整除 因为这是前缀和 妙!!

额外说明

SQL Server讲课笔记06:实施数据完整性

文章目录 一、数据完整性 二、实体完整性 (一)主键约束 (二)唯一约束 三、域完整性 (一)空值约束 (二)默认约束 (三)检查约束 四、引用完整性 (一)概述 (二)案例演示 五、约束操作 (一)删除约束 (二)禁用约束 六、补充操作 (一)规则操作

ads via 小工具