Java線程池實(shí)現(xiàn)帶返回值的方式方法
Java線程池帶返回值的方式方法
在Java中,線程池是一種重要的多線程處理方式,可以有效管理和重用線程,提高程序的性能和效率。有時(shí)候我們需要在多線程處理中獲取線程的返回值,本文將介紹如何使用線程池實(shí)現(xiàn)帶返回值的方式方法。
使用Callable和Future
Java中的Callable接口是一種帶返回值的多線程處理方式,結(jié)合Future接口可以實(shí)現(xiàn)獲取線程返回值的功能。下面是一個(gè)示例代碼:
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 { // 在這里編寫具體的任務(wù)邏輯 return 42; // 返回一個(gè)整數(shù)結(jié)果 } }; Future<Integer> future = executor.submit(task); try { Integer result = future.get(); System.out.println("線程返回值為:" + result); } catch (Exception e) { e.printStackTrace(); } executor.shutdown(); } }
在上面的示例中,我們創(chuàng)建了一個(gè)Callable匿名類來(lái)實(shí)現(xiàn)具體的任務(wù)邏輯,然后將其提交給線程池進(jìn)行處理。通過(guò)Future的get()方法可以獲取到線程的返回值。
使用CompletionService
除了上面的方法,還可以使用CompletionService來(lái)更加靈活地實(shí)現(xiàn)帶返回值的線程處理,下面是一個(gè)示例代碼:
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 { // 在這里編寫具體的任務(wù)邏輯 return 42; // 返回一個(gè)整數(shù)結(jié)果 } }; completionService.submit(task); Future<Integer> future = completionService.take(); Integer result = future.get(); System.out.println("線程返回值為:" + result); executor.shutdown(); } }
在這個(gè)示例中,我們使用了CompletionService來(lái)管理任務(wù)的執(zhí)行和獲取返回值,通過(guò)take()方法獲取最先完成的任務(wù)結(jié)果。 通過(guò)以上方法,我們可以實(shí)現(xiàn)在Java中使用線程池帶返回值的方式方法,更好地控制和處理多線程任務(wù),并獲取線程處理的結(jié)果。希望本文對(duì)您有所幫助。
會(huì)遇到需要處理大量數(shù)據(jù)的情況,使用線程池可以提高數(shù)據(jù)處理的效率。下面是一個(gè)示例場(chǎng)景:假設(shè)我們有一個(gè)包含大量任務(wù)的列表,每個(gè)任務(wù)需要處理一條數(shù)據(jù),并返回處理結(jié)果。我們可以利用線程池來(lái)同時(shí)處理這些任務(wù),最后獲取結(jié)果并進(jìn)行統(tǒng)計(jì)。
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) { // 模擬生成大量任務(wù)數(shù)據(jù) List<String> dataList = generateDataList(100); // 創(chuàng)建線程池 ExecutorService executor = Executors.newFixedThreadPool(5); // 定義任務(wù)列表 List<Callable<Integer>> tasks = new ArrayList<>(); for (String data : dataList) { tasks.add(() -> { // 模擬數(shù)據(jù)處理,這里使用隨機(jī)數(shù)表示處理結(jié)果 Random random = new Random(); return random.nextInt(100); }); } // 批量提交任務(wù) 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("所有任務(wù)處理完成,結(jié)果總和為:" + totalResult); // 關(guān)閉線程池 executor.shutdown(); } // 模擬生成大量數(shù)據(jù)的方法 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; } }
在上述示例中,我們模擬了一個(gè)需要處理大量數(shù)據(jù)的場(chǎng)景,使用線程池并行處理任務(wù)并獲取處理結(jié)果,在最后統(tǒng)計(jì)所有任務(wù)的處理結(jié)果。這種場(chǎng)景可以幫助提高數(shù)據(jù)處理的效率,特別是對(duì)于大規(guī)模數(shù)據(jù)的處理。
線程池是一種管理和復(fù)用線程的機(jī)制,它可以在程序運(yùn)行時(shí)創(chuàng)建一定數(shù)量的線程,并且在有任務(wù)到來(lái)時(shí)分配線程執(zhí)行任務(wù),執(zhí)行完畢后將線程返回線程池以備重用,從而避免頻繁地創(chuàng)建和銷毀線程,提高了線程的利用率和系統(tǒng)的性能。 下面是線程池的一些重要特點(diǎn)和優(yōu)點(diǎn):
- 重用線程: 線程池會(huì)在內(nèi)部維護(hù)一定數(shù)量的線程,這些線程可以被重復(fù)利用,而不是每次執(zhí)行任務(wù)都要?jiǎng)?chuàng)建新線程,減少了線程創(chuàng)建和銷毀的開銷。
- 控制最大并發(fā)數(shù): 線程池可以限制可以同時(shí)執(zhí)行的線程數(shù)量,可以避免因?yàn)榫€程過(guò)多導(dǎo)致系統(tǒng)資源耗盡的問(wèn)題。
- 管理線程: 線程池可以對(duì)線程的生命周期進(jìn)行管理,包括線程的創(chuàng)建、重用、銷毀等操作,讓線程的操作更加可控。
- 提高響應(yīng)速度: 線程池可以讓任務(wù)立即執(zhí)行,而不需要等待線程的創(chuàng)建,提高了任務(wù)的響應(yīng)速度。
- 降低系統(tǒng)開銷: 使用線程池可以有效控制系統(tǒng)中線程的數(shù)量,避免線程爆炸式增長(zhǎng),從而減少了系統(tǒng)資源的開銷。 常見的線程池類型包括:FixedThreadPool(固定大小線程池)、CachedThreadPool(緩存線程池)、SingleThreadPool(單線程池)和 ScheduledThreadPool(定時(shí)任務(wù)線程池)等。
拓展:java多線程帶返回值的方式方法
java利用線程池帶有返回值的方式,大體邏輯批量處理大量數(shù)據(jù),啟用線程池,處理完成后將所有的返回內(nèi)容進(jìn)行組裝拼接
廢話不多說(shuō)開始看代碼,重點(diǎn)敲黑板:
1.ThreadPoolExecutor 線程池創(chuàng)建
2.CountDownLatch 同步工具類,讓主線程一直等待,直到子線程執(zhí)行完后再執(zhí)行
3.listret 用于接收多線程返回值
方式一
使用線程池
// 創(chuàng)建線程池 ThreadPoolExecutor executor = new ThreadPoolExecutor(coresNumber * 2, coresNumber * 2 + 1, 1000, TimeUnit.MINUTES, new LinkedBlockingDeque<>()); /*創(chuàng)建List用來(lái)接收多線程返回的內(nèi)容,泛型里面可以自定義,String或者對(duì)象亦或者其他類型*/ List<Map<String, Object>> listret = new ArrayList<>(); // 同步工具類,讓主線程一直等待,直到子線程執(zhí)行完后再執(zhí)行 CountDownLatch downLatch = new CountDownLatch(partition.size()); // 循環(huán)任務(wù)的List for (List<String> stringList : partition) { // 啟用開啟多個(gè)線程 executor.execute(new Runnable() { @Override public void run() { try { // 開始調(diào)用具體業(yè)務(wù)代碼 Map<String, Object> mapRet = pmpTargetPriceService.targetPriceThreadTask(stringList, initiateTaskType, userName); listret.add(mapRet); } catch (Exception e) { logger.error("循環(huán)開啟線多線程報(bào)錯(cuò),調(diào)用下游系統(tǒng)出現(xiàn)錯(cuò)誤,異常:" + e); } finally { // 業(yè)務(wù)邏輯處理完畢,計(jì)數(shù)器減一【當(dāng)前線程處理任務(wù)完畢,線程釋放進(jìn)入線程池,等待處理下一個(gè)任務(wù)】 downLatch.countDown(); } } }); } // 主線程需要等待子任務(wù)線程執(zhí)行完,結(jié)果匯總之后,主線程繼續(xù)往下執(zhí)行 try { downLatch.await(); } catch (Exception e) { logger.error("等待超時(shí)", e); throw new RuntimeException("系統(tǒng)處理超時(shí),請(qǐng)稍后再試"); } // 對(duì)返回組裝的list進(jìn)循環(huán)處理業(yè)務(wù)邏輯 for (Map<String, Object> esbResultPlm1 : listret) { // 從Future對(duì)象上獲取任務(wù)的返回值,并輸出到控制臺(tái) // Map esbResultPlm1 = (Map) f.get(); // todo 對(duì)我返回的多個(gè)map進(jìn)行拼接 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; } }
方法一得到的結(jié)果如下,使用線程池我這里是核數(shù)乘以2是核心線程16,最大17,所以這里最多是16個(gè)線程,而且他是無(wú)序的隨機(jī)分配的
方式二
重點(diǎn)不用線程池使用@Async注解,但是策略得有所調(diào)整,大體邏輯比如你待處理的數(shù)據(jù)有100條,你可以將這個(gè)List按10條為一個(gè)新的List,循環(huán)這個(gè)集合,在調(diào)用的實(shí)際方法上加@Async注解,從而實(shí)現(xiàn)多線程加快循環(huán)也是可以的
@Async注意點(diǎn),加了該注解的方法不能再同一個(gè)類,否則無(wú)效,其次有可能存在啟動(dòng)過(guò)程@Async UnsatisfiedDependencyException導(dǎo)致 SpringBoot 無(wú)法啟動(dòng)問(wèn)題解決,我這里是在報(bào)錯(cuò)的類里有注入service或者mapper的注解上加了@Lazy注解就可以
// 將要發(fā)送的集合按10個(gè)一組進(jìn)行重新組裝 List<List<String>> partition = Lists.partition(list, 10); /*創(chuàng)建List用來(lái)接收多線程返回的內(nèi)容,泛型里面可以自定義,String或者對(duì)象亦或者其他類型*/ List<Map<String, Object>> listret = new ArrayList<>(); // 循環(huán)任務(wù)的List for (List<String> stringList : partition) { // 開始調(diào)用具體業(yè)務(wù)代碼 Map<String, Object> mapRet = pmpTargetPriceService.targetPriceThreadTask(stringList, initiateTaskType, userName); listret.add(mapRet); } // 對(duì)返回組裝的list進(jìn)循環(huán)處理業(yè)務(wù)邏輯 for (Map<String, Object> esbResultPlm1 : listret) { //對(duì)返回的內(nèi)容進(jìn)行業(yè)務(wù)處理 } // 調(diào)用的方法,返回map @Async public Map<String, Object> targetPriceThreadTask(List<String> idList, String initiateTaskType, String userName) throws Exception { //具體的邏輯代碼 Map<String, Object> map = new HashMap(); return map; }
方法二的執(zhí)行結(jié)果,循環(huán)多少次就啟動(dòng)了多少個(gè)子線程,所以這里的想法是先將原生數(shù)組按自定義個(gè)進(jìn)行分配,如有200個(gè)任務(wù),分給20個(gè)人,每人10個(gè)大概就是這樣的思路
我的完整代碼僅供參考,里面很多類都是我自己業(yè)務(wù)用到的,大家可以借鑒
public Map<String, Object> initiateTargetPriceTask(PmpTargetPriceDTO pmpTargetPriceDTO) throws Exception { String userName = SecurityUtils.getUsername(); Map map = new HashMap(); List<String> list = Arrays.asList(pmpTargetPriceDTO.getIds()); // 將要發(fā)送的集合按10個(gè)一組進(jìn)行重新組裝 List<List<String>> partition = Lists.partition(list, 10); // 創(chuàng)建一個(gè)線程池 // 獲取CPU核數(shù) int coresNumber = Runtime.getRuntime().availableProcessors(); System.out.println("獲取CPU核數(shù):" + coresNumber); // 創(chuàng)建線程池 ThreadPoolExecutor executor = new ThreadPoolExecutor(coresNumber * 2, coresNumber * 2 + 1, 1000, TimeUnit.MINUTES, new LinkedBlockingDeque<>()); // 獲取任務(wù)發(fā)起類型字段 String initiateTaskType = pmpTargetPriceDTO.getInitiateTaskType(); /*創(chuàng)建List用來(lái)接收多線程返回的內(nèi)容,泛型里面可以自定義,String或者對(duì)象亦或者其他類型*/ List<Map<String, Object>> listret = new ArrayList<>(); // 同步工具類,讓主線程一直等待,直到子線程執(zhí)行完后再執(zhí)行 CountDownLatch downLatch = new CountDownLatch(partition.size()); // 循環(huán)任務(wù)的List for (List<String> stringList : partition) { // 啟用開啟多個(gè)線程 executor.execute(new Runnable() { @Override public void run() { try { // 開始調(diào)用具體業(yè)務(wù)代碼 Map<String, Object> mapRet = pmpTargetPriceService.targetPriceThreadTask(stringList, initiateTaskType, userName); listret.add(mapRet); } catch (Exception e) { logger.error("循環(huán)開啟線多線程報(bào)錯(cuò),調(diào)用下游系統(tǒng)出現(xiàn)錯(cuò)誤,異常:" + e); } finally { // 業(yè)務(wù)邏輯處理完畢,計(jì)數(shù)器減一【當(dāng)前線程處理任務(wù)完畢,線程釋放進(jìn)入線程池,等待處理下一個(gè)任務(wù)】 downLatch.countDown(); } } }); } // 主線程需要等待子任務(wù)線程執(zhí)行完,結(jié)果匯總之后,主線程繼續(xù)往下執(zhí)行 try { downLatch.await(); } catch (Exception e) { logger.error("等待超時(shí)", e); throw new RuntimeException("系統(tǒng)處理超時(shí),請(qǐng)稍后再試"); } // 關(guān)閉線程池 executor.shutdown(); // 獲取所有并發(fā)任務(wù)的運(yùn)行結(jié)果 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對(duì)象上獲取任務(wù)的返回值,并輸出到控制臺(tái) // Map esbResultPlm1 = (Map) f.get(); // todo 對(duì)我返回的多個(gè)map進(jìn)行拼接 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 對(duì)最終的結(jié)果進(jìn)行組裝 if (failureNumCount > 0) { failureMsg.insert(0, "很抱歉,發(fā)起任務(wù)存在失敗!共發(fā)起 " + list.size() + "條數(shù)據(jù),其中有" + failureNumCount + " 條數(shù)據(jù)格式不正確,錯(cuò)誤如下:"); map.put("status", "fail"); map.put("msg", failureMsg.toString()); } else { successMsg.insert(0, "恭喜您,數(shù)據(jù)已全部發(fā)起成功!共 " + successNumCount + " 條"); map.put("status", "success"); map.put("msg", successMsg.toString()); } return map; } // 調(diào)用的邏輯處理方法 public Map<String, Object> targetPriceThreadTask(List<String> idList, String initiateTaskType, String userName) throws Exception { // 發(fā)起目標(biāo)價(jià)任務(wù) int successNum = 0; int failureNum = 0; StringBuilder successMsg = new StringBuilder(); StringBuilder failureMsg = new StringBuilder(); StringBuffer NoSubunitmaterialCode = new StringBuffer(); // 子組不存在的物料號(hào)合集 StringBuffer NoSubunit = new StringBuffer(); // 沒有子組的子組號(hào)合集 Map<String, Object> map = new HashMap(); for (String id : idList) { PmpTargetPrice pmpTargetPrice = pmpTargetPriceMapper.selectPmpTargetPriceById(id); SysApiRequestLog sysApiRequestLog = new SysApiRequestLog(); sysApiRequestLog.setRequestMethod("手動(dòng)發(fā)起目標(biāo)價(jià)任務(wù)"); sysApiRequestLog.setRequestData("物料號(hào):" + pmpTargetPrice.getMaterialCode()); //查詢是否發(fā)起流程, if (pmpTargetPrice.getIsFqlc().equals("1")) { failureNum++; String msg = "<br/>物料號(hào):" + pmpTargetPrice.getMaterialCode() + "、此物料已經(jīng)發(fā)起過(guò)流程,請(qǐng)核實(shí)!"; failureMsg.append(msg); continue; } PmpTargetPriceProcess targetPriceProcess = new PmpTargetPriceProcess(); // 請(qǐng)求PLM接口 Map invokeGetPlm = invokeWebService.getInvokeGetPlm(pmpTargetPrice.getMaterialCode()); targetPriceProcess.setSouce("手動(dòng)發(fā)起"); // 來(lái)源(手動(dòng)發(fā)起) targetPriceProcess.setTaskSponsor(userName); // 設(shè)置發(fā)起人 targetPriceProcess.setMaterialStatus("0"); // 狀態(tài) targetPriceProcess.setInitiateTaskType(initiateTaskType); // 設(shè)置手工發(fā)起任務(wù)類型 if (null != invokeGetPlm.get("number").toString()) { targetPriceProcess.setMaterialCode(invokeGetPlm.get("number").toString()); // 物料編號(hào) } 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()); // 狀態(tài) } // 請(qǐng)求BOM接口獲取數(shù)據(jù) Map materialCode = invokeWebService.getEsbBomMaterialInfo(pmpTargetPrice.getMaterialCode()); // 截取物料編碼為子組號(hào) String substring = pmpTargetPriceProcessService.getBlockCode(pmpTargetPrice.getMaterialCode()); PmpTargetRule targetRule = new PmpTargetRule(); PmpTargetRule pmpTargetRule; String userCode = ""; // 判斷bom是否有返回,有返回表示有路線,無(wú)返回表示無(wú)路線 if (null != materialCode) { //根據(jù)物料編號(hào)截取的子組取目標(biāo)規(guī)則表PMP_TARGET_RULE中查 targetRule.setSonGroup(substring); targetRule.setIsRoute("1"); pmpTargetRule = pmpTargetRuleService.selectPmpTargetRuleBySonGroup(targetRule); // 判斷<pmpTargetRule>子組配置是否存在,如根據(jù)子組查詢不存在則設(shè)置為特殊子組 if (!Optional.ofNullable(pmpTargetRule).isPresent()) { targetRule.setSonGroup("特殊件無(wú)法獲取"); targetRule.setIsRoute("1"); pmpTargetRule = pmpTargetRuleService.selectPmpTargetRuleBySonGroup(targetRule); } /** * 1.一級(jí)制造、一級(jí)裝配和采購(gòu)制造均為空時(shí)生成任務(wù); * 2.一級(jí)制造、一級(jí)裝配和采購(gòu)制造均有值時(shí)生成任務(wù); * 3.一級(jí)制造、一級(jí)裝配有值,采購(gòu)制造為空時(shí),不生成任務(wù)。但要判定一級(jí)制造和一級(jí)裝配均不含CG時(shí)為自制件, * 不生成任務(wù),但返回PLM為S,提示“一級(jí)制造和一級(jí)裝配均不含CG,為自制件,不生成任務(wù)”, * 其他情況返回PLM為E并提示“非自制件,BOM采購(gòu)制造路線待維護(hù),請(qǐng)稍后發(fā)起定價(jià)任務(wù)”。 */ String mfmrtg = ""; // 一級(jí)制造 String mfartg = ""; // 一級(jí)裝配 if (StringUtils.isNotBlank(materialCode.get("MFMRTG").toString()) && StringUtils.isNotBlank(materialCode.get("MFARTG").toString()) ) { mfmrtg = materialCode.get("MFMRTG").toString(); // 一級(jí)制造 mfartg = materialCode.get("MFARTG").toString(); // 一級(jí)裝配 } else { failureNum++; logger.error("物料號(hào):" + pmpTargetPrice.getMaterialCode() + "獲取BOM信息,一級(jí)制造或一級(jí)裝配為Null,發(fā)起任務(wù)失??!"); String msg = "<br/>物料號(hào):" + pmpTargetPrice.getMaterialCode() + "、獲取BOM信息,一級(jí)制造或一級(jí)裝配為Null,發(fā)起任務(wù)失??! "; failureMsg.append(msg); sysApiRequestLog.setResponseStatus(EsbResult.RET_STATUS_ERROR); sysApiRequestLog.setErrorLog("手動(dòng)發(fā)起目標(biāo)價(jià)任務(wù),失敗原因:根據(jù)物料號(hào)獲取BOM信息,一級(jí)制造或一級(jí)裝配為Null,發(fā)起任務(wù)失敗"); apiRequestLogService.insertSysApiRequestLog(sysApiRequestLog); continue; } // if (StringUtils.isNotBlank(materialCode.get("MFMRTG").toString())) { // targetPriceProcess.setOneLevelMake(materialCode.get("MFMRTG").toString()); // 一級(jí)制造 // } // if (StringUtils.isNotBlank(materialCode.get("MFARTG").toString())) { // targetPriceProcess.setOneLevelAssembling(materialCode.get("MFARTG").toString()); // 一級(jí)裝配 // } targetPriceProcess.setOneLevelMake(mfmrtg); // 一級(jí)制造 targetPriceProcess.setOneLevelAssembling(mfartg); // 一級(jí)裝配 if (StringUtils.isNotBlank(materialCode.get("CFMRTG").toString())) { targetPriceProcess.setPurchaseMake(materialCode.get("CFMRTG").toString()); // 采購(gòu)制造 //根據(jù)BOM接口返回采購(gòu)制造,如果是PT為研究院,否則為財(cái)務(wù)部 if (targetPriceProcess.getPurchaseMake().equals("PT")) { if (!StringUtils.isEmpty(pmpTargetRule.getYjyDirectorCode())) { targetPriceProcess.setTaskPurchase(pmpTargetRule.getYjyDirectorCode()); // 指定填寫目標(biāo)價(jià)人:研究院 // 設(shè)置審核人 String[] splitYjyCode = pmpTargetRule.getYjyDirectorCode().split("/"); userCode = splitYjyCode[0]; } else { failureNum++; String msg = "<br/>物料號(hào):" + pmpTargetPrice.getMaterialCode() + "、未獲取到研究院相關(guān)人員,請(qǐng)核對(duì)! "; failureMsg.append(msg); logger.error("手動(dòng)發(fā)起目標(biāo)價(jià)任務(wù)-物料號(hào)-PT-YJY:" + pmpTargetPrice.getMaterialCode() + "設(shè)置目標(biāo)價(jià)錄入人時(shí)配置有誤,路線為PT,根據(jù)子組查詢但是研究院人員code是未維護(hù)發(fā)起任務(wù)失??!"); sysApiRequestLog.setResponseStatus(EsbResult.RET_STATUS_ERROR); sysApiRequestLog.setErrorLog("手動(dòng)發(fā)起目標(biāo)價(jià)任務(wù)失敗,失敗原因:路線為PT,根據(jù)子組查詢但是研究院人員code是未維護(hù)發(fā)起任務(wù)失敗"); apiRequestLogService.insertSysApiRequestLog(sysApiRequestLog); NoSubunitmaterialCode.append("物料號(hào)-PT-YJY:" + pmpTargetPrice.getMaterialCode() + "/"); NoSubunit.append("子組號(hào)-PT-YJY:" + substring + "/"); continue; } } else { if (!StringUtils.isEmpty(pmpTargetRule.getCwDirectorCode())) { targetPriceProcess.setTaskPurchase(pmpTargetRule.getCwDirectorCode()); // 指定填寫目標(biāo)價(jià)人:財(cái)務(wù)部 // 設(shè)置審核人 String[] splitCwCode = pmpTargetRule.getCwDirectorCode().split("/"); userCode = splitCwCode[0]; } else { failureNum++; String msg = "<br/>物料號(hào):" + pmpTargetPrice.getMaterialCode() + "、未獲取到財(cái)務(wù)部相關(guān)人員,請(qǐng)核對(duì)! "; failureMsg.append(msg); logger.error("手動(dòng)發(fā)起目標(biāo)價(jià)任務(wù)-物料號(hào)-非PT-CW:" + pmpTargetPrice.getMaterialCode() + "設(shè)置目標(biāo)價(jià)錄入人時(shí)配置有誤,路線非PT,根據(jù)子組查詢財(cái)務(wù)人員code是Null發(fā)起任務(wù)失?。?); sysApiRequestLog.setResponseStatus(EsbResult.RET_STATUS_ERROR); sysApiRequestLog.setErrorLog("手動(dòng)發(fā)起目標(biāo)價(jià)任務(wù),失敗原因:根據(jù)子組查詢財(cái)務(wù)人員code是Null發(fā)起任務(wù)失敗"); apiRequestLogService.insertSysApiRequestLog(sysApiRequestLog); NoSubunitmaterialCode.append("物料號(hào)-非PT-CW:" + pmpTargetPrice.getMaterialCode() + "/"); NoSubunit.append("子組號(hào)-非PT-CW:" + substring + "/"); continue; } } } else { if (!mfmrtg.equals("CG") || !mfartg.equals("CG")) { logger.error("物料號(hào):" + pmpTargetPrice.getMaterialCode() + "一級(jí)制造和一級(jí)裝配均不含CG,為自制件,不生成任務(wù)!"); failureNum++; String msg = "<br/>物料號(hào):" + pmpTargetPrice.getMaterialCode() + "、一級(jí)制造和一級(jí)裝配均不含CG,為自制件,不生成任務(wù)! "; failureMsg.append(msg); sysApiRequestLog.setResponseStatus(EsbResult.RET_STATUS_ERROR); sysApiRequestLog.setErrorLog("手動(dòng)發(fā)起目標(biāo)價(jià)任務(wù),失敗原因:一級(jí)制造和一級(jí)裝配均不含CG,為自制件,不生成任務(wù)!"); continue; } else { failureNum++; String msg = "<br/>物料號(hào):" + pmpTargetPrice.getMaterialCode() + "、BOM采購(gòu)制造路線待維護(hù),請(qǐng)稍后發(fā)起定價(jià)任務(wù)!"; failureMsg.append(msg); sysApiRequestLog.setResponseStatus(EsbResult.RET_STATUS_ERROR); sysApiRequestLog.setErrorLog("手動(dòng)發(fā)起目標(biāo)價(jià)任務(wù),失敗原因:BOM采購(gòu)制造路線待維護(hù),請(qǐng)稍后發(fā)起定價(jià)任務(wù)!"); continue; } } } else { // 無(wú)路線 targetRule.setSonGroup(substring); targetRule.setIsRoute("0"); pmpTargetRule = pmpTargetRuleService.selectPmpTargetRuleBySonGroup(targetRule); /** * 其他特殊件,無(wú)法獲取子組, * PT或無(wú)路線由研究院鄭宇處理, * 非PT的由財(cái)務(wù)部蘇戰(zhàn)波和趙偉處理 */ if (!Optional.ofNullable(pmpTargetRule).isPresent()) { targetRule.setSonGroup("特殊件無(wú)法獲取"); targetRule.setIsRoute("1"); pmpTargetRule = pmpTargetRuleService.selectPmpTargetRuleBySonGroup(targetRule); } if (null != pmpTargetRule && StringUtils.isNotBlank(pmpTargetRule.getYjyDirectorCode())) { targetPriceProcess.setTaskPurchase(pmpTargetRule.getYjyDirectorCode()); // 指定填寫目標(biāo)價(jià)人:研究院 String[] splitYjyCode = pmpTargetRule.getYjyDirectorCode().split("/"); userCode = splitYjyCode[0]; } else { failureNum++; String msg = "<br/>物料號(hào):" + pmpTargetPrice.getMaterialCode() + "、未獲取到研究院相關(guān)人員(無(wú)路線),請(qǐng)核對(duì)! "; failureMsg.append(msg); continue; } } // todo 判斷任務(wù)是研究院或者財(cái)務(wù),設(shè)置審核人 // 查詢研究院,財(cái)務(wù)或者無(wú)路線任務(wù)辦理人,并獲取他們的部門編碼,向上尋找審核人 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(); } //查詢審核配置表,查到審核人,插入目標(biāo)價(jià) PmpTargetAuditConfig pmpTargetAuditConfig = pmpTargetAuditConfigService.selectPmpTargetAuditConfigByDeptCode(deptCode); targetPriceProcess.setCheckName(pmpTargetAuditConfig.getAuditor()); } } //已發(fā)起流程 pmpTargetPrice.setIsFqlc("1"); targetPriceProcess.setStatus("0"); // 任務(wù)狀態(tài) 0待定級(jí)發(fā)起 targetPriceProcess.setQuejiaType("目標(biāo)價(jià)"); // 缺價(jià)類型默認(rèn)目標(biāo)價(jià) //添加任務(wù)發(fā)起人 targetPriceProcess.setTaskSponsor(userName); targetPriceProcess.setCreateBy(userName); pmpTargetPriceMapper.updatePmpTargetPrice(pmpTargetPrice); if (StringUtils.isEmpty(targetPriceProcess.getMaterialName())) { targetPriceProcess.setMaterialName(pmpTargetPrice.getMaterialName()); } /** * 查看當(dāng)前物料號(hào)在目標(biāo)價(jià)任務(wù)表中是否存在,最后的檢查 */ PmpTargetPriceProcess priceProcess = new PmpTargetPriceProcess(); priceProcess.setMaterialCode(targetPriceProcess.getMaterialCode()); priceProcess.setStatus("0,1,2,4"); PmpTargetPriceProcess pmpTargetPriceProcess = targetPriceProcessService.selectPmpTargetPriceProcessByEntity(priceProcess); if (null != pmpTargetPriceProcess) { continue; } // 設(shè)置任務(wù)號(hào) String newsNo = DateUtils.parseDateToStr("yyyyMMdd", new Date()); int count = targetPriceProcessService.getFindTaskCount(); String format = String.format("%05d", count); // 任務(wù)編號(hào) MBJRW+年月日+流水號(hào) targetPriceProcess.setTaskNumber("MBJRW" + newsNo + format); targetPriceProcessService.insertPmpTargetPriceProcess(targetPriceProcess); successNum++; } if (failureNum > 0) { // failureMsg.insert(0, "很抱歉,發(fā)起任務(wù)存在失??!共 " + failureNum + " 條數(shù)據(jù)格式不正確,錯(cuò)誤如下:"); map.put("status", "fail"); map.put("msg", failureMsg.toString()); map.put("failureNum", failureNum); } else { // successMsg.insert(0, "恭喜您,數(shù)據(jù)已全部發(fā)起成功!共 " + successNum + " 條"); map.put("status", "success"); map.put("msg", successMsg.toString()); map.put("successNum", successNum); } logger.info("手動(dòng)發(fā)起目標(biāo)價(jià)任務(wù)結(jié)束!"); logger.info("手動(dòng)發(fā)起目標(biāo)價(jià)-物料號(hào)查找子組有誤的物料統(tǒng)計(jì):" + NoSubunitmaterialCode.toString()); logger.info("手動(dòng)發(fā)起目標(biāo)價(jià)-物料號(hào)查找子組有誤的子組號(hào)統(tǒng)計(jì):" + NoSubunit.toString()); return map; }
總結(jié)方式一和方式二都能解決加快任務(wù)處理,處理時(shí)間都差不讀多,大家可以挑選自己適合的方式,如有更好的方式或不對(duì)的點(diǎn)請(qǐng)指正,歡迎大家溝通交流,共同成長(zhǎng)進(jìn)步
到此這篇關(guān)于Java線程池實(shí)現(xiàn)帶返回值的方式方法的文章就介紹到這了,更多相關(guān)Java線程池帶返回值內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java如何將二維數(shù)組轉(zhuǎn)化為一維數(shù)組
這篇文章主要介紹了Java如何將二維數(shù)組轉(zhuǎn)化為一維數(shù)組,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08IDEA 使用mybatis插件Free Mybatis plugin的步驟(推薦)
這篇文章主要介紹了IDEA 使用mybatis插件Free Mybatis plugin的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12解決spring項(xiàng)目找不到Aspect依賴注解的問(wèn)題
這篇文章主要介紹了解決spring項(xiàng)目找不到Aspect依賴注解的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06詳解SpringCloud Ribbon 負(fù)載均衡通過(guò)服務(wù)器名無(wú)法連接的神坑
這篇文章主要介紹了詳解SpringCloud Ribbon 負(fù)載均衡通過(guò)服務(wù)器名無(wú)法連接的神坑,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-06-06詳解Java如何實(shí)現(xiàn)一個(gè)BlockingQueue
這篇文章主要為大家詳細(xì)介紹了Java如何實(shí)現(xiàn)一個(gè)BlockingQueue阻塞隊(duì)列,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-06-06java實(shí)現(xiàn)同步的幾種方式(示例詳解)
這篇文章主要介紹了java實(shí)現(xiàn)同步的幾種方式,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2024-12-12Java實(shí)現(xiàn)將枚舉類轉(zhuǎn)為json并返回給前端
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)將枚舉類轉(zhuǎn)為json并返回給前端的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12