java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java线程池带返回值

Java线程池实现带返回值的方式方法

作者:牛肉胡辣汤

在Java中,线程池是一种重要的多线程处理方式,可以有效管理和重用线程,提高程序的性能和效率,有时候我们需要在多线程处理中获取线程的返回值,本文将介绍如何使用线程池实现带返回值的方式方法,需要的朋友可以参考下

Java线程池带返回值的方式方法

在Java中,线程池是一种重要的多线程处理方式,可以有效管理和重用线程,提高程序的性能和效率。有时候我们需要在多线程处理中获取线程的返回值,本文将介绍如何使用线程池实现带返回值的方式方法。

使用Callable和Future

Java中的Callable接口是一种带返回值的多线程处理方式,结合Future接口可以实现获取线程返回值的功能。下面是一个示例代码:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ThreadPoolWithReturnValueExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(1);
        Callable<Integer> task = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                // 在这里编写具体的任务逻辑
                return 42; // 返回一个整数结果
            }
        };
        Future<Integer> future = executor.submit(task);
        try {
            Integer result = future.get();
            System.out.println("线程返回值为:" + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        executor.shutdown();
    }
}

在上面的示例中,我们创建了一个Callable匿名类来实现具体的任务逻辑,然后将其提交给线程池进行处理。通过Futureget()方法可以获取到线程的返回值。

使用CompletionService

除了上面的方法,还可以使用CompletionService来更加灵活地实现带返回值的线程处理,下面是一个示例代码:

import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ThreadPoolWithReturnValueExample {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newFixedThreadPool(1);
        CompletionService<Integer> completionService = new ExecutorCompletionService<>(executor);
        Callable<Integer> task = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                // 在这里编写具体的任务逻辑
                return 42; // 返回一个整数结果
            }
        };
        completionService.submit(task);
        Future<Integer> future = completionService.take();
        Integer result = future.get();
        System.out.println("线程返回值为:" + result);
        executor.shutdown();
    }
}

在这个示例中,我们使用了CompletionService来管理任务的执行和获取返回值,通过take()方法获取最先完成的任务结果。 通过以上方法,我们可以实现在Java中使用线程池带返回值的方式方法,更好地控制和处理多线程任务,并获取线程处理的结果。希望本文对您有所帮助。

会遇到需要处理大量数据的情况,使用线程池可以提高数据处理的效率。下面是一个示例场景:假设我们有一个包含大量任务的列表,每个任务需要处理一条数据,并返回处理结果。我们可以利用线程池来同时处理这些任务,最后获取结果并进行统计。

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;
public class ThreadPoolBatchDataProcessing {
    public static void main(String[] args) {
        // 模拟生成大量任务数据
        List<String> dataList = generateDataList(100);
        // 创建线程池
        ExecutorService executor = Executors.newFixedThreadPool(5);
        // 定义任务列表
        List<Callable<Integer>> tasks = new ArrayList<>();
        for (String data : dataList) {
            tasks.add(() -> {
                // 模拟数据处理,这里使用随机数表示处理结果
                Random random = new Random();
                return random.nextInt(100);
            });
        }
        // 批量提交任务
        List<Future<Integer>> futures;
        try {
            futures = executor.invokeAll(tasks);
        } catch (InterruptedException e) {
            e.printStackTrace();
            return;
        }
        int totalResult = 0;
        for (Future<Integer> future : futures) {
            try {
                totalResult += future.get();
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
        System.out.println("所有任务处理完成,结果总和为:" + totalResult);
        // 关闭线程池
        executor.shutdown();
    }
    // 模拟生成大量数据的方法
    private static List<String> generateDataList(int size) {
        List<String> dataList = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            dataList.add("Data-" + i);
        }
        return dataList;
    }
}

在上述示例中,我们模拟了一个需要处理大量数据的场景,使用线程池并行处理任务并获取处理结果,在最后统计所有任务的处理结果。这种场景可以帮助提高数据处理的效率,特别是对于大规模数据的处理。

线程池是一种管理和复用线程的机制,它可以在程序运行时创建一定数量的线程,并且在有任务到来时分配线程执行任务,执行完毕后将线程返回线程池以备重用,从而避免频繁地创建和销毁线程,提高了线程的利用率和系统的性能。 下面是线程池的一些重要特点和优点:

  1. 重用线程: 线程池会在内部维护一定数量的线程,这些线程可以被重复利用,而不是每次执行任务都要创建新线程,减少了线程创建和销毁的开销。
  2. 控制最大并发数: 线程池可以限制可以同时执行的线程数量,可以避免因为线程过多导致系统资源耗尽的问题。
  3. 管理线程: 线程池可以对线程的生命周期进行管理,包括线程的创建、重用、销毁等操作,让线程的操作更加可控。
  4. 提高响应速度: 线程池可以让任务立即执行,而不需要等待线程的创建,提高了任务的响应速度。
  5. 降低系统开销: 使用线程池可以有效控制系统中线程的数量,避免线程爆炸式增长,从而减少了系统资源的开销。 常见的线程池类型包括:FixedThreadPool(固定大小线程池)、CachedThreadPool(缓存线程池)、SingleThreadPool(单线程池)和 ScheduledThreadPool(定时任务线程池)等。

拓展:java多线程带返回值的方式方法

java利用线程池带有返回值的方式,大体逻辑批量处理大量数据,启用线程池,处理完成后将所有的返回内容进行组装拼接

废话不多说开始看代码,重点敲黑板:

1.ThreadPoolExecutor 线程池创建

2.CountDownLatch 同步工具类,让主线程一直等待,直到子线程执行完后再执行

在这里插入图片描述

3.listret 用于接收多线程返回值

方式一

使用线程池

// 创建线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(coresNumber * 2, coresNumber * 2 + 1, 1000, TimeUnit.MINUTES, new LinkedBlockingDeque<>());
         /*创建List用来接收多线程返回的内容,泛型里面可以自定义,String或者对象亦或者其他类型*/
        List<Map<String, Object>> listret = new ArrayList<>();
         // 同步工具类,让主线程一直等待,直到子线程执行完后再执行
        CountDownLatch downLatch = new CountDownLatch(partition.size());
        // 循环任务的List
        for (List<String> stringList : partition) {
            // 启用开启多个线程
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 开始调用具体业务代码
                        Map<String, Object> mapRet = pmpTargetPriceService.targetPriceThreadTask(stringList, initiateTaskType, userName);
                        listret.add(mapRet);
                    } catch (Exception e) {
                        logger.error("循环开启线多线程报错,调用下游系统出现错误,异常:" + e);
                    } finally {
                        // 业务逻辑处理完毕,计数器减一【当前线程处理任务完毕,线程释放进入线程池,等待处理下一个任务】
                        downLatch.countDown();
                    }
                }
            });
        }
         // 主线程需要等待子任务线程执行完,结果汇总之后,主线程继续往下执行
        try {
            downLatch.await();
        } catch (Exception e) {
            logger.error("等待超时", e);
            throw new RuntimeException("系统处理超时,请稍后再试");
        }
        // 对返回组装的list进循环处理业务逻辑
        for (Map<String, Object> esbResultPlm1 : listret) {
            // 从Future对象上获取任务的返回值,并输出到控制台
//            Map esbResultPlm1 = (Map) f.get();
            // todo 对我返回的多个map进行拼接
            if (esbResultPlm1.get("status").equals("fail")) {
                failureNum = (int) esbResultPlm1.get("failureNum");
                failureMsg.append(esbResultPlm1.get("msg"));
                map.put("msg", failureMsg.toString());
                failureNumCount += failureNum;

            } else {
                successNum = (int) esbResultPlm1.get("successNum");
                successMsg.append(esbResultPlm1.get("msg"));
                map.put("msg", successMsg.toString());
                successNumCount += successNum;
            }
        }

方法一得到的结果如下,使用线程池我这里是核数乘以2是核心线程16,最大17,所以这里最多是16个线程,而且他是无序的随机分配的

在这里插入图片描述

在这里插入图片描述

方式二

重点不用线程池使用@Async注解,但是策略得有所调整,大体逻辑比如你待处理的数据有100条,你可以将这个List按10条为一个新的List,循环这个集合,在调用的实际方法上加@Async注解,从而实现多线程加快循环也是可以的

@Async注意点,加了该注解的方法不能再同一个类,否则无效,其次有可能存在启动过程@Async UnsatisfiedDependencyException导致 SpringBoot 无法启动问题解决,我这里是在报错的类里有注入service或者mapper的注解上加了@Lazy注解就可以

在这里插入图片描述

        // 将要发送的集合按10个一组进行重新组装
        List<List<String>> partition = Lists.partition(list, 10);
         /*创建List用来接收多线程返回的内容,泛型里面可以自定义,String或者对象亦或者其他类型*/
        List<Map<String, Object>> listret = new ArrayList<>();
        // 循环任务的List
        for (List<String> stringList : partition) {
            // 开始调用具体业务代码
            Map<String, Object> mapRet = pmpTargetPriceService.targetPriceThreadTask(stringList, initiateTaskType, userName);
            listret.add(mapRet);
         }
        // 对返回组装的list进循环处理业务逻辑
        for (Map<String, Object> esbResultPlm1 : listret) {
           //对返回的内容进行业务处理
        }
        
// 调用的方法,返回map
 	@Async
    public Map<String, Object> targetPriceThreadTask(List<String> idList, String initiateTaskType, String userName) throws Exception {
        //具体的逻辑代码
        Map<String, Object> map = new HashMap();
        return map;
    }

方法二的执行结果,循环多少次就启动了多少个子线程,所以这里的想法是先将原生数组按自定义个进行分配,如有200个任务,分给20个人,每人10个大概就是这样的思路

在这里插入图片描述

在这里插入图片描述

我的完整代码仅供参考,里面很多类都是我自己业务用到的,大家可以借鉴

 public Map<String, Object> initiateTargetPriceTask(PmpTargetPriceDTO pmpTargetPriceDTO) throws Exception {
        String userName = SecurityUtils.getUsername();
        Map map = new HashMap();
        List<String> list = Arrays.asList(pmpTargetPriceDTO.getIds());
        // 将要发送的集合按10个一组进行重新组装
        List<List<String>> partition = Lists.partition(list, 10);
        // 创建一个线程池
        // 获取CPU核数
        int coresNumber = Runtime.getRuntime().availableProcessors();
        System.out.println("获取CPU核数:" + coresNumber);
        // 创建线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(coresNumber * 2, coresNumber * 2 + 1, 1000, TimeUnit.MINUTES, new LinkedBlockingDeque<>());
        // 获取任务发起类型字段
        String initiateTaskType = pmpTargetPriceDTO.getInitiateTaskType();
        /*创建List用来接收多线程返回的内容,泛型里面可以自定义,String或者对象亦或者其他类型*/
        List<Map<String, Object>> listret = new ArrayList<>();
        // 同步工具类,让主线程一直等待,直到子线程执行完后再执行
        CountDownLatch downLatch = new CountDownLatch(partition.size());
        // 循环任务的List
        for (List<String> stringList : partition) {
            // 启用开启多个线程
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 开始调用具体业务代码
                        Map<String, Object> mapRet = pmpTargetPriceService.targetPriceThreadTask(stringList, initiateTaskType, userName);
                        listret.add(mapRet);
                    } catch (Exception e) {
                        logger.error("循环开启线多线程报错,调用下游系统出现错误,异常:" + e);
                    } finally {
                        // 业务逻辑处理完毕,计数器减一【当前线程处理任务完毕,线程释放进入线程池,等待处理下一个任务】
                        downLatch.countDown();
                    }
                }
            });
        }
        // 主线程需要等待子任务线程执行完,结果汇总之后,主线程继续往下执行
        try {
            downLatch.await();
        } catch (Exception e) {
            logger.error("等待超时", e);
            throw new RuntimeException("系统处理超时,请稍后再试");
        }
        // 关闭线程池
        executor.shutdown();

        // 获取所有并发任务的运行结果
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        int failureNum;
        int successNum;
        int failureNumCount = 0;
        int successNumCount = 0;
        for (Map<String, Object> esbResultPlm1 : listret) {
            // 从Future对象上获取任务的返回值,并输出到控制台
//            Map esbResultPlm1 = (Map) f.get();
            // todo 对我返回的多个map进行拼接
            if (esbResultPlm1.get("status").equals("fail")) {
                failureNum = (int) esbResultPlm1.get("failureNum");
                failureMsg.append(esbResultPlm1.get("msg"));
                map.put("msg", failureMsg.toString());
                failureNumCount += failureNum;

            } else {
                successNum = (int) esbResultPlm1.get("successNum");
                successMsg.append(esbResultPlm1.get("msg"));
                map.put("msg", successMsg.toString());
                successNumCount += successNum;
            }
        }

//        todo 对最终的结果进行组装
        if (failureNumCount > 0) {
            failureMsg.insert(0, "很抱歉,发起任务存在失败!共发起 " + list.size() + "条数据,其中有" + failureNumCount + " 条数据格式不正确,错误如下:");
            map.put("status", "fail");
            map.put("msg", failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您,数据已全部发起成功!共 " + successNumCount + " 条");
            map.put("status", "success");
            map.put("msg", successMsg.toString());
        }
        return map;
    }
    
    // 调用的逻辑处理方法
	public Map<String, Object> targetPriceThreadTask(List<String> idList, String initiateTaskType, String userName) throws Exception {
        // 发起目标价任务
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        StringBuffer NoSubunitmaterialCode = new StringBuffer(); // 子组不存在的物料号合集
        StringBuffer NoSubunit = new StringBuffer(); // 没有子组的子组号合集
        Map<String, Object> map = new HashMap();
        for (String id : idList) {
            PmpTargetPrice pmpTargetPrice = pmpTargetPriceMapper.selectPmpTargetPriceById(id);
            SysApiRequestLog sysApiRequestLog = new SysApiRequestLog();
            sysApiRequestLog.setRequestMethod("手动发起目标价任务");
            sysApiRequestLog.setRequestData("物料号:" + pmpTargetPrice.getMaterialCode());
            //查询是否发起流程,
            if (pmpTargetPrice.getIsFqlc().equals("1")) {
                failureNum++;
                String msg = "<br/>物料号:" + pmpTargetPrice.getMaterialCode() + "、此物料已经发起过流程,请核实!";
                failureMsg.append(msg);
                continue;
            }
            PmpTargetPriceProcess targetPriceProcess = new PmpTargetPriceProcess();
            //  请求PLM接口
            Map invokeGetPlm = invokeWebService.getInvokeGetPlm(pmpTargetPrice.getMaterialCode());
            targetPriceProcess.setSouce("手动发起"); // 来源(手动发起)
            targetPriceProcess.setTaskSponsor(userName);  // 设置发起人
            targetPriceProcess.setMaterialStatus("0"); // 状态
            targetPriceProcess.setInitiateTaskType(initiateTaskType); // 设置手工发起任务类型
            if (null != invokeGetPlm.get("number").toString()) {
                targetPriceProcess.setMaterialCode(invokeGetPlm.get("number").toString());  // 物料编号
            }
            if (null != invokeGetPlm.get("name").toString()) {
                targetPriceProcess.setMaterialName(invokeGetPlm.get("name").toString());  // 物料名称
            }
            if (null != invokeGetPlm.get("phase").toString()) {
                targetPriceProcess.setStage(invokeGetPlm.get("phase").toString());//阶段
            }
            if (null != invokeGetPlm.get("version").toString()) {
                targetPriceProcess.setVersionNo(invokeGetPlm.get("version").toString()); // 大版本
            }
            if (null != invokeGetPlm.get("state").toString()) {
                targetPriceProcess.setMaterialStatus(invokeGetPlm.get("state").toString()); // 状态
            }

            // 请求BOM接口获取数据
            Map materialCode = invokeWebService.getEsbBomMaterialInfo(pmpTargetPrice.getMaterialCode());
            // 截取物料编码为子组号
            String substring = pmpTargetPriceProcessService.getBlockCode(pmpTargetPrice.getMaterialCode());
            PmpTargetRule targetRule = new PmpTargetRule();
            PmpTargetRule pmpTargetRule;
            String userCode = "";
            // 判断bom是否有返回,有返回表示有路线,无返回表示无路线
            if (null != materialCode) {
                //根据物料编号截取的子组取目标规则表PMP_TARGET_RULE中查
                targetRule.setSonGroup(substring);
                targetRule.setIsRoute("1");
                pmpTargetRule = pmpTargetRuleService.selectPmpTargetRuleBySonGroup(targetRule);

                // 判断<pmpTargetRule>子组配置是否存在,如根据子组查询不存在则设置为特殊子组
                if (!Optional.ofNullable(pmpTargetRule).isPresent()) {
                    targetRule.setSonGroup("特殊件无法获取");
                    targetRule.setIsRoute("1");
                    pmpTargetRule = pmpTargetRuleService.selectPmpTargetRuleBySonGroup(targetRule);
                }
                /**
                 * 1.一级制造、一级装配和采购制造均为空时生成任务;
                 * 2.一级制造、一级装配和采购制造均有值时生成任务;
                 * 3.一级制造、一级装配有值,采购制造为空时,不生成任务。但要判定一级制造和一级装配均不含CG时为自制件,
                 * 不生成任务,但返回PLM为S,提示“一级制造和一级装配均不含CG,为自制件,不生成任务”,
                 * 其他情况返回PLM为E并提示“非自制件,BOM采购制造路线待维护,请稍后发起定价任务”。
                 */
                String mfmrtg = ""; // 一级制造
                String mfartg = ""; // 一级装配
                if (StringUtils.isNotBlank(materialCode.get("MFMRTG").toString())
                        && StringUtils.isNotBlank(materialCode.get("MFARTG").toString())
                ) {
                    mfmrtg = materialCode.get("MFMRTG").toString(); // 一级制造
                    mfartg = materialCode.get("MFARTG").toString(); // 一级装配
                } else {
                    failureNum++;
                    logger.error("物料号:" + pmpTargetPrice.getMaterialCode() + "获取BOM信息,一级制造或一级装配为Null,发起任务失败!");
                    String msg = "<br/>物料号:" + pmpTargetPrice.getMaterialCode() + "、获取BOM信息,一级制造或一级装配为Null,发起任务失败! ";
                    failureMsg.append(msg);
                    sysApiRequestLog.setResponseStatus(EsbResult.RET_STATUS_ERROR);
                    sysApiRequestLog.setErrorLog("手动发起目标价任务,失败原因:根据物料号获取BOM信息,一级制造或一级装配为Null,发起任务失败");
                    apiRequestLogService.insertSysApiRequestLog(sysApiRequestLog);
                    continue;
                }
//                if (StringUtils.isNotBlank(materialCode.get("MFMRTG").toString())) {
//                    targetPriceProcess.setOneLevelMake(materialCode.get("MFMRTG").toString());  // 一级制造
//                }
//                if (StringUtils.isNotBlank(materialCode.get("MFARTG").toString())) {
//                    targetPriceProcess.setOneLevelAssembling(materialCode.get("MFARTG").toString()); // 一级装配
//                }
                targetPriceProcess.setOneLevelMake(mfmrtg);  // 一级制造
                targetPriceProcess.setOneLevelAssembling(mfartg); // 一级装配
                if (StringUtils.isNotBlank(materialCode.get("CFMRTG").toString())) {
                    targetPriceProcess.setPurchaseMake(materialCode.get("CFMRTG").toString());  // 采购制造
                    //根据BOM接口返回采购制造,如果是PT为研究院,否则为财务部
                    if (targetPriceProcess.getPurchaseMake().equals("PT")) {
                        if (!StringUtils.isEmpty(pmpTargetRule.getYjyDirectorCode())) {
                            targetPriceProcess.setTaskPurchase(pmpTargetRule.getYjyDirectorCode()); // 指定填写目标价人:研究院
                            // 设置审核人
                            String[] splitYjyCode = pmpTargetRule.getYjyDirectorCode().split("/");
                            userCode = splitYjyCode[0];
                        } else {
                            failureNum++;
                            String msg = "<br/>物料号:" + pmpTargetPrice.getMaterialCode() + "、未获取到研究院相关人员,请核对! ";
                            failureMsg.append(msg);
                            logger.error("手动发起目标价任务-物料号-PT-YJY:" + pmpTargetPrice.getMaterialCode() + "设置目标价录入人时配置有误,路线为PT,根据子组查询但是研究院人员code是未维护发起任务失败!");
                            sysApiRequestLog.setResponseStatus(EsbResult.RET_STATUS_ERROR);
                            sysApiRequestLog.setErrorLog("手动发起目标价任务失败,失败原因:路线为PT,根据子组查询但是研究院人员code是未维护发起任务失败");
                            apiRequestLogService.insertSysApiRequestLog(sysApiRequestLog);
                            NoSubunitmaterialCode.append("物料号-PT-YJY:" + pmpTargetPrice.getMaterialCode() + "/");
                            NoSubunit.append("子组号-PT-YJY:" + substring + "/");
                            continue;
                        }
                    } else {
                        if (!StringUtils.isEmpty(pmpTargetRule.getCwDirectorCode())) {
                            targetPriceProcess.setTaskPurchase(pmpTargetRule.getCwDirectorCode()); // 指定填写目标价人:财务部
                            // 设置审核人
                            String[] splitCwCode = pmpTargetRule.getCwDirectorCode().split("/");
                            userCode = splitCwCode[0];
                        } else {
                            failureNum++;
                            String msg = "<br/>物料号:" + pmpTargetPrice.getMaterialCode() + "、未获取到财务部相关人员,请核对! ";
                            failureMsg.append(msg);
                            logger.error("手动发起目标价任务-物料号-非PT-CW:" + pmpTargetPrice.getMaterialCode() + "设置目标价录入人时配置有误,路线非PT,根据子组查询财务人员code是Null发起任务失败!");
                            sysApiRequestLog.setResponseStatus(EsbResult.RET_STATUS_ERROR);
                            sysApiRequestLog.setErrorLog("手动发起目标价任务,失败原因:根据子组查询财务人员code是Null发起任务失败");
                            apiRequestLogService.insertSysApiRequestLog(sysApiRequestLog);
                            NoSubunitmaterialCode.append("物料号-非PT-CW:" + pmpTargetPrice.getMaterialCode() + "/");
                            NoSubunit.append("子组号-非PT-CW:" + substring + "/");
                            continue;
                        }
                    }
                } else {
                    if (!mfmrtg.equals("CG") || !mfartg.equals("CG")) {
                        logger.error("物料号:" + pmpTargetPrice.getMaterialCode() + "一级制造和一级装配均不含CG,为自制件,不生成任务!");
                        failureNum++;
                        String msg = "<br/>物料号:" + pmpTargetPrice.getMaterialCode() + "、一级制造和一级装配均不含CG,为自制件,不生成任务! ";
                        failureMsg.append(msg);
                        sysApiRequestLog.setResponseStatus(EsbResult.RET_STATUS_ERROR);
                        sysApiRequestLog.setErrorLog("手动发起目标价任务,失败原因:一级制造和一级装配均不含CG,为自制件,不生成任务!");
                        continue;
                    } else {
                        failureNum++;
                        String msg = "<br/>物料号:" + pmpTargetPrice.getMaterialCode() + "、BOM采购制造路线待维护,请稍后发起定价任务!";
                        failureMsg.append(msg);
                        sysApiRequestLog.setResponseStatus(EsbResult.RET_STATUS_ERROR);
                        sysApiRequestLog.setErrorLog("手动发起目标价任务,失败原因:BOM采购制造路线待维护,请稍后发起定价任务!");
                        continue;
                    }
                }
            } else {
                // 无路线
                targetRule.setSonGroup(substring);
                targetRule.setIsRoute("0");
                pmpTargetRule = pmpTargetRuleService.selectPmpTargetRuleBySonGroup(targetRule);
                /**
                 * 其他特殊件,无法获取子组,
                 * PT或无路线由研究院郑宇处理,
                 * 非PT的由财务部苏战波和赵伟处理
                 */
                if (!Optional.ofNullable(pmpTargetRule).isPresent()) {
                    targetRule.setSonGroup("特殊件无法获取");
                    targetRule.setIsRoute("1");
                    pmpTargetRule = pmpTargetRuleService.selectPmpTargetRuleBySonGroup(targetRule);
                }
                if (null != pmpTargetRule && StringUtils.isNotBlank(pmpTargetRule.getYjyDirectorCode())) {
                    targetPriceProcess.setTaskPurchase(pmpTargetRule.getYjyDirectorCode()); // 指定填写目标价人:研究院
                    String[] splitYjyCode = pmpTargetRule.getYjyDirectorCode().split("/");
                    userCode = splitYjyCode[0];
                } else {
                    failureNum++;
                    String msg = "<br/>物料号:" + pmpTargetPrice.getMaterialCode() + "、未获取到研究院相关人员(无路线),请核对! ";
                    failureMsg.append(msg);
                    continue;
                }
            }

            // todo 判断任务是研究院或者财务,设置审核人
            // 查询研究院,财务或者无路线任务办理人,并获取他们的部门编码,向上寻找审核人
            if (!userCode.equals("")) {
                SysUser sysUser = userService.selectUserByUserName(userCode);
                if (StringUtils.isNotNull(sysUser)) {
                    // 截取部门code
                    String deptCode = "";
                    if (sysUser.getDeptId().length() > 9) {
                        deptCode = sysUser.getDeptId().substring(0, 9);
                    } else {
                        deptCode = sysUser.getDeptId();
                    }
                    //查询审核配置表,查到审核人,插入目标价
                    PmpTargetAuditConfig pmpTargetAuditConfig = pmpTargetAuditConfigService.selectPmpTargetAuditConfigByDeptCode(deptCode);
                    targetPriceProcess.setCheckName(pmpTargetAuditConfig.getAuditor());
                }
            }
            //已发起流程
            pmpTargetPrice.setIsFqlc("1");
            targetPriceProcess.setStatus("0"); // 任务状态 0待定级发起
            targetPriceProcess.setQuejiaType("目标价"); // 缺价类型默认目标价
            //添加任务发起人
            targetPriceProcess.setTaskSponsor(userName);
            targetPriceProcess.setCreateBy(userName);
            pmpTargetPriceMapper.updatePmpTargetPrice(pmpTargetPrice);
            if (StringUtils.isEmpty(targetPriceProcess.getMaterialName())) {
                targetPriceProcess.setMaterialName(pmpTargetPrice.getMaterialName());
            }
            /**
             * 查看当前物料号在目标价任务表中是否存在,最后的检查
             */
            PmpTargetPriceProcess priceProcess = new PmpTargetPriceProcess();
            priceProcess.setMaterialCode(targetPriceProcess.getMaterialCode());
            priceProcess.setStatus("0,1,2,4");
            PmpTargetPriceProcess pmpTargetPriceProcess = targetPriceProcessService.selectPmpTargetPriceProcessByEntity(priceProcess);
            if (null != pmpTargetPriceProcess) {
                continue;
            }
            // 设置任务号
            String newsNo = DateUtils.parseDateToStr("yyyyMMdd", new Date());
            int count = targetPriceProcessService.getFindTaskCount();
            String format = String.format("%05d", count);
            //  任务编号 MBJRW+年月日+流水号
            targetPriceProcess.setTaskNumber("MBJRW" + newsNo + format);
            targetPriceProcessService.insertPmpTargetPriceProcess(targetPriceProcess);
            successNum++;
        }
        if (failureNum > 0) {
//            failureMsg.insert(0, "很抱歉,发起任务存在失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
            map.put("status", "fail");
            map.put("msg", failureMsg.toString());
            map.put("failureNum", failureNum);
        } else {
//            successMsg.insert(0, "恭喜您,数据已全部发起成功!共 " + successNum + " 条");
            map.put("status", "success");
            map.put("msg", successMsg.toString());
            map.put("successNum", successNum);
        }
        logger.info("手动发起目标价任务结束!");
        logger.info("手动发起目标价-物料号查找子组有误的物料统计:" + NoSubunitmaterialCode.toString());
        logger.info("手动发起目标价-物料号查找子组有误的子组号统计:" + NoSubunit.toString());
        return map;
    }
    

总结方式一和方式二都能解决加快任务处理,处理时间都差不读多,大家可以挑选自己适合的方式,如有更好的方式或不对的点请指正,欢迎大家沟通交流,共同成长进步

到此这篇关于Java线程池实现带返回值的方式方法的文章就介绍到这了,更多相关Java线程池带返回值内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文