<转>ThreadPoolExecutor

本文详细介绍了Java中的线程池ThreadPoolExecutor,包括其构造函数、工作流程及如何配置参数等内容。通过实例展示了线程池的使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文地址:http://jiaguwen123.iteye.com/blog/1017636
从 Java 5 开始,Java 提供了自己的线程池。线程池就是一个线程的容器,每次只执行额定数量的线程。 java.util.concurrent.ThreadPoolExecutor 就是这样的线程池。它很灵活,但使用起来也比较复杂,本文就对其做一个介绍。

  首先是构造函数。以最简单的构造函数为例:

public ThreadPoolExecutor(   

int corePoolSize,   

int maximumPoolSize,   

long keepAliveTime,   

TimeUnit unit,   

BlockingQueue<Runnable> workQueue)  

  看起来挺复杂的。这里介绍一下。

  corePoolSize 指的是保留的线程池大小。

  maximumPoolSize 指的是线程池的最大大小。

  keepAliveTime 指的是空闲线程结束的超时时间。

  unit 是一个枚举,表示 keepAliveTime 的单位。

  workQueue 表示存放任务的队列。

  我们可以从线程池的工作过程中了解这些参数的意义。线程池的工作过程如下:

  1、线程池刚创建时,里面没有一个线程。任务队列是作为参数传进来的。不过,就算队列里面有任务,线程池也不会马上执行它们。

  2、当调用 execute() 方法添加一个任务时,线程池会做如下判断:

   a. 如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务;

   b. 如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列。

   c. 如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要创建线程运行这个任务;

   d. 如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会抛出异常,告诉调用者“我不能再接受任务了”。

  3、当一个线程完成任务时,它会从队列中取下一个任务来执行。

4、当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于 corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。

   这样的过程说明,并不是先加入任务就一定会先执行。假设队列大小为 10,corePoolSize 为 3,maximumPoolSize 为 6,那么当加入 20 个任务时,执行的顺序就是这样的:首先执行任务 1、2、3,然后任务 4~13 被放入队列。这时候队列满了,任务 14、15、16 会被马上执行,而任务 17~20 则会抛出异常。最终顺序是:1、2、3、14、15、16、4、5、6、7、8、9、10、11、12、13。下面是一个线程池使用的例子:

public static void main(String[] args) {   

BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();   

ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 1, TimeUnit.DAYS, queue);   


for (int i = 0; i < 20; i++) {   

executor.execute(new Runnable() {   


public void run() {   

try {   

Thread.sleep(1000);   

} catch (InterruptedException e) {   

e.printStackTrace();   

}   

System.out.println(String.format("thread %d finished", this.hashCode()));   

}   

});   

}   

executor.shutdown();   

}  

  对这个例子的说明如下:

   1、BlockingQueue 只是一个接口,常用的实现类有 LinkedBlockingQueue 和 ArrayBlockingQueue。用 LinkedBlockingQueue 的好处在于没有大小限制。这样的话,因为队列不会满,所以 execute() 不会抛出异常,而线程池中运行的线程数也永远不会超过 corePoolSize 个,keepAliveTime 参数也就没有意义了。

  2、shutdown() 方法不会阻塞。调用 shutdown() 方法之后,主线程就马上结束了,而线程池会继续运行直到所有任务执行完才会停止。如果不调用 shutdown() 方法,那么线程池会一直保持下去,以便随时添加新的任务。

  到这里对于这个线程池还只是介绍了一小部分。ThreadPoolExecutor 具有很强的可扩展性,不过扩展它的前提是要熟悉它的工作方式。后面的文章将会介绍如何扩展 ThreadPoolExecutor 类。

  java.util.concurrent.ThreadPoolExecutor 类提供了丰富的可扩展性。你可以通过创建它的子类来自定义它的行为。例如,我希望当每个任务结束之后打印一条消息,但我又无法修改任务对象,那么我可以这样写:

  除了 afterExecute 方法之外,ThreadPoolExecutor 类还有 beforeExecute() 和 terminated() 方法可以重写,分别是在任务执行之前和整个线程池停止之后执行。

   除了可以添加任务执行前后的动作之外, ThreadPoolExecutor 还允许你自定义当添加任务失败后的执行策略。你可以调用线程池的 setRejectedExecutionHandler() 方法,用自定义的 RejectedExecutionHandler 对象替换现有的策略。 ThreadPoolExecutor 提供 4 个现有的策略,分别是:

  ThreadPoolExecutor.AbortPolicy:表示拒绝任务并抛出异常

  ThreadPoolExecutor.DiscardPolicy:表示拒绝任务但不做任何动作

  ThreadPoolExecutor.CallerRunsPolicy:表示拒绝任务,并在调用者的线程中直接执行该任务

  ThreadPoolExecutor.DiscardOldestPolicy:表示先丢弃任务队列中的第一个任务,然后把这个任务加进队列。

  这里是一个例子:

ThreadPoolExecutor executor = new ThreadPoolExecutor(size, maxSize, 1, TimeUnit.DAYS, queue);

executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());

  除此之外,你也可以通过实现 RejectedExecutionHandler 接口来编写自己的策略。下面是一个例子:

 

ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 1, TimeUnit.SECONDS, queue,
new RejectedExecutionHandler() {
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println(String.format("Task %d rejected.", r.hashCode()));
}
}

);
LambdaQueryWrapperX<Sheet> wrapperX = new LambdaQueryWrapperX<>(); wrapperX.ne(Sheet::getStatus, 11) .between(Sheet::getCreateTime, dto.getStartTime(), dto.getEndTime()); List<Sheet> sheetList = getMapper().selectList(wrapperX); // Assert.state(!sheetList.isEmpty(), "该时间范围内工单为空"); //获取导出数据列表map //定损物料 List<SheetDamageDetail> sheetDamageDetails = sheetDamageDetailService.selectList(new LambdaQueryWrapperX<>()); Map<String, List<SheetDamageDetail>> damageDetailMap = sheetDamageDetails.stream().collect(Collectors.groupingBy(SheetDamageDetail::getSheetId)); List<SheetExamineDetail> sheetExamineDetails = sheetExamineDetailService.selectList(new LambdaQueryWrapperX<>()); Map<String, List<SheetExamineDetail>> examineDetailMap = sheetExamineDetails.stream().collect(Collectors.groupingBy(SheetExamineDetail::getSheetId)); //返修物料 List<SheetFixDetail> sheetFixDetails = sheetFixDetailService.selectList(new LambdaQueryWrapperX<>()); Map<String, List<SheetFixDetail>> fixDetailMap = sheetFixDetails.stream().collect(Collectors.groupingBy(SheetFixDetail::getSheetId)); //退料物料 List<SheetFixReturnMaterials> fixReturnMaterials = sheetFixReturnMaterialsService.selectList(new LambdaQueryWrapperX<>()); Map<String, List<SheetFixReturnMaterials>> fixReturnMaterialMap = fixReturnMaterials.stream().collect(Collectors.groupingBy(SheetFixReturnMaterials::getSheetId)); //工单时间 List<SheetProgress> sheetProgresses = sheetProgressService.selectList(new LambdaQueryWrapperX<>()); Map<String, List<SheetProgress>> progressMap = sheetProgresses.stream().collect(Collectors.groupingBy(SheetProgress::getSheetId)); List<ExcelExportVO> list = new ArrayList<>(); for (Sheet sheet : sheetList) { //定损物料 List<SheetDamageDetail> examineList = new ArrayList<>(); if (dto.getFieldList().contains("examineNumber")) { if (SheetServerType.CUSTOMER_EXCHANGE.equals(sheet.getServerType()) || SheetServerType.FOREIGN_EXCHANGE.equals(sheet.getServerType())) { } else if (SheetServerType.INTERNAL_DEVICE_FIX.equals(sheet.getServerType()) || SheetServerType.CUSTOMER_DEVICE_FIX.equals(sheet.getServerType())) { if (ObjectUtil.isNotNull(damageDetailMap.get(sheet.getId()))) { examineList = damageDetailMap.get(sheet.getId()); } } else { List<SheetExamineDetail> sheetExamineDetailList = examineDetailMap.get(sheet.getId()); if (ObjectUtil.isNotNull(sheetExamineDetailList)) { examineList = mapperFacade.mapAsList(sheetExamineDetailList, SheetDamageDetail.class); } } } //返修物料 List<SheetFixDetail> fixRepairList = new ArrayList<>(); if (dto.getFieldList().contains("fixRepairNumber") && ObjectUtil.isNotNull(fixDetailMap.get(sheet.getId()))) { fixRepairList = fixDetailMap.get(sheet.getId()); } //退料物料 List<SheetFixReturnMaterials> fixReturnList = new ArrayList<>(); if (dto.getFieldList().contains("fixReturnNumber") && ObjectUtil.isNotNull(fixReturnMaterialMap.get(sheet.getId()))) { fixReturnList = fixReturnMaterialMap.get(sheet.getId()); } if (examineList.isEmpty() && fixRepairList.isEmpty() && fixReturnList.isEmpty()) { ExcelExportVO vo = mapperFacade.map(sheet, ExcelExportVO.class); extracted(sheet, vo, progressMap); list.add(vo); } if (examineList.size() >= fixRepairList.size() && examineList.size() >= fixReturnList.size()) { for (int i = 0; i < examineList.size(); i++) { ExcelExportVO vo = mapperFacade.map(sheet, ExcelExportVO.class); extracted(sheet, vo, progressMap); vo.setExamineMaterialName(examineList.get(i).getMaterialName()); vo.setExamineNumber(examineList.get(i).getNumber()); vo.setExamineCount(examineList.get(i).getCount()); vo.setExaminePrice(examineList.get(i).getPrice()); if (i < fixRepairList.size()) { vo.setFixRepairMaterialName(fixRepairList.get(i).getMaterialName()); vo.setFixRepairNumber(fixRepairList.get(i).getNumber()); vo.setFixRepairCount(fixRepairList.get(i).getCount()); } if (i < fixReturnList.size()) { vo.setFixReturnMaterialName(fixReturnList.get(i).getMaterialName()); vo.setFixReturnNumber(fixReturnList.get(i).getNumber()); vo.setFixReturnCount(fixReturnList.get(i).getCount()); } list.add(vo); } } else if (fixRepairList.size() >= examineList.size() && fixRepairList.size() >= fixReturnList.size()) { for (int i = 0; i < fixRepairList.size(); i++) { ExcelExportVO vo = mapperFacade.map(sheet, ExcelExportVO.class); extracted(sheet, vo, progressMap); vo.setFixRepairMaterialName(fixRepairList.get(i).getMaterialName()); vo.setFixRepairNumber(fixRepairList.get(i).getNumber()); vo.setFixRepairCount(fixRepairList.get(i).getCount()); if (i < examineList.size()) { vo.setExamineMaterialName(examineList.get(i).getMaterialName()); vo.setExamineNumber(examineList.get(i).getNumber()); vo.setExamineCount(examineList.get(i).getCount()); vo.setExaminePrice(examineList.get(i).getPrice()); } if (i < fixReturnList.size()) { vo.setFixReturnMaterialName(fixReturnList.get(i).getMaterialName()); vo.setFixReturnNumber(fixReturnList.get(i).getNumber()); vo.setFixReturnCount(fixReturnList.get(i).getCount()); } list.add(vo); } } else { for (int i = 0; i < fixReturnList.size(); i++) { ExcelExportVO vo = mapperFacade.map(sheet, ExcelExportVO.class); extracted(sheet, vo, progressMap); vo.setFixReturnMaterialName(fixReturnList.get(i).getMaterialName()); vo.setFixReturnNumber(fixReturnList.get(i).getNumber()); vo.setFixReturnCount(fixReturnList.get(i).getCount()); if (i < examineList.size()) { vo.setExamineMaterialName(examineList.get(i).getMaterialName()); vo.setExamineNumber(examineList.get(i).getNumber()); vo.setExamineCount(examineList.get(i).getCount()); vo.setExaminePrice(examineList.get(i).getPrice()); } if (i < fixRepairList.size()) { vo.setFixRepairMaterialName(fixRepairList.get(i).getMaterialName()); vo.setFixRepairNumber(fixRepairList.get(i).getNumber()); vo.setFixRepairCount(fixRepairList.get(i).getCount()); } list.add(vo); } } } return list; } private void extracted(Sheet sheet, ExcelExportVO vo, Map<String, List<SheetProgress>> progressMap) { try { //基础信息-问题 CompletableFuture<WebSheetDetailCaseInfoVO> sheetDetailCaseInfoFuture = CompletableFuture.supplyAsync(() -> getWebSheetDetailCaseInfoVO(sheet.getId()), taskExecutor); //基础信息-原因 CompletableFuture<WebSheetDetailDamageVO> sheetDetailDamageFuture = CompletableFuture.supplyAsync(() -> getWebSheetDetailDamageVO(sheet), taskExecutor); //基础信息-价格 CompletableFuture<WebSheetDetailExamineVO> sheetDetailExamineFuture = CompletableFuture.supplyAsync(() -> getWebSheetDetailExamineVO(sheet), taskExecutor); //客户信息-寄件信息 CompletableFuture<WebSheetDetailCustomerLogisticsVO> sheetDetailLogisticsFuture = CompletableFuture.supplyAsync(() -> getWebSheetDetailCustomerLogisticsVO(sheet), taskExecutor); //客户信息-收件信息 CompletableFuture<WebSheetDetailSendVO> sheetDetailSendFuture = CompletableFuture.supplyAsync(() -> getWebSheetDetailSendVO(sheet), taskExecutor); //发票信息 CompletableFuture<WebSheetDetailInvoiceVO> sheetDetailInvoiceFuture = CompletableFuture.supplyAsync(() -> getWebSheetDetailInvoiceVO(sheet), taskExecutor); CompletableFuture.allOf(sheetDetailCaseInfoFuture, sheetDetailDamageFuture, sheetDetailExamineFuture, sheetDetailLogisticsFuture, sheetDetailSendFuture, sheetDetailInvoiceFuture); //基础信息-原因 WebSheetDetailDamageVO sheetDetailDamageVO = sheetDetailDamageFuture.get(); if (ObjectUtil.isNotNull(sheetDetailDamageVO)) { mapperFacade.map(sheetDetailDamageVO, vo); if (ObjectUtils.isNotEmpty(sheetDetailDamageVO.getProblemDetail())) { vo.setProblemDetailDescription(sheetDetailDamageVO.getProblemDetail()); } if (ObjectUtils.isNotEmpty(sheetDetailDamageVO.getDutyReasonList())) { vo.setDutyReasonList(sheetDetailDamageVO.getDutyReasonList().toString()); } } //基础信息-问题 WebSheetDetailCaseInfoVO sheetDetailCaseInfoVO = sheetDetailCaseInfoFuture.get(); if (ObjectUtil.isNotNull(sheetDetailCaseInfoVO)) { mapperFacade.map(sheetDetailCaseInfoVO, vo); if (ObjectUtils.isNotEmpty(sheetDetailCaseInfoVO.getParentProblems())) { vo.setParentProblems(sheetDetailCaseInfoVO.getParentProblems().toString()); } if (ObjectUtils.isNotEmpty(sheetDetailCaseInfoVO.getChildProblems())) { vo.setChildProblems(sheetDetailCaseInfoVO.getChildProblems().toString()); } } //基础信息-价格 WebSheetDetailExamineVO sheetDetailExamineVO = sheetDetailExamineFuture.get(); if (ObjectUtil.isNotNull(sheetDetailExamineVO)) { mapperFacade.map(sheetDetailExamineVO, vo); } //工单时间 List<SheetProgress> sheetProgresses = progressMap.get(sheet.getId()); sheetProgresses.forEach(progress -> ProgressStatus.fromName(progress.getProgress()).ifPresent(status -> status.apply(vo, progress)) ); //客户信息-寄件信息 WebSheetDetailCustomerLogisticsVO sheetDetailLogisticsVO = sheetDetailLogisticsFuture.get(); if (ObjectUtil.isNotNull(sheetDetailLogisticsVO)) { vo.setSenderUsername(sheetDetailLogisticsVO.getUsername()); vo.setSenderMobile(sheetDetailLogisticsVO.getMobile()); vo.setSenderEmail(sheetDetailLogisticsVO.getEmail()); vo.setSenderAddress(sheetDetailLogisticsVO.getAddress()); vo.setSenderUnit(sheetDetailLogisticsVO.getUnit()); vo.setSenderCompany(sheetDetailLogisticsVO.getCompany()); vo.setSenderNumber(sheetDetailLogisticsVO.getNumber()); } //客户信息-收件信息 WebSheetDetailSendVO sheetDetailSendVO = sheetDetailSendFuture.get(); if (ObjectUtil.isNotNull(sheetDetailSendVO)) { vo.setReceiverName(sheetDetailSendVO.getUsername()); vo.setReceiverMobile(sheetDetailSendVO.getMobile()); vo.setReceiverEmail(sheetDetailSendVO.getEmail()); vo.setReceiverAddress(sheetDetailSendVO.getAddress()); vo.setReceiverCompany(sheetDetailSendVO.getCompany()); vo.setReceiverNumber(sheetDetailSendVO.getNumber()); } //发票信息 WebSheetDetailInvoiceVO sheetDetailInvoiceVO = sheetDetailInvoiceFuture.get(); if (ObjectUtil.isNotNull(sheetDetailInvoiceVO)) { mapperFacade.map(sheetDetailInvoiceVO, vo); } vo.setAccount(sheet.getCustomerPhone()); vo.setStatus(sheet.getStatus()); } catch (Exception e) { log.error("自定义导出工单详情异常", e); throw new ServiceException("自定义导出工单详情异常"); } }这段代码帮我优化一下 提高运行速度和优雅代码
最新发布
08-01
@SneakyThrows public List<File> wordToPdf(List<String> fileUrl,IConverter converter){ log.info("---------------------wordpdf--开始--------------------------"); List<File> pdfFiles = new ArrayList<>(); ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2); // 调整池大小以适应需求 List<Future<File>> futures = new ArrayList<>(); for (String url : fileUrl) { futures.add(executorService.submit(() -> { int index = 0; if (url.endsWith(".docx")) { index = url.lastIndexOf(".docx"); } else { index = url.lastIndexOf(".doc"); } String outFilePath = url.substring(0, index);; // 获取输出文件路径 return wordToPdf(url, outFilePath, converter); })); } for (Future<File> future : futures) { try { pdfFiles.add(future.get()); // 收集结果, 阻塞直到任务完成 } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } executorService.shutdown(); log.info("---------------------wordpdf--结束--------------------------"); return pdfFiles; } @SneakyThrows public File wordToPdf(String filePath, String outFilePath,IConverter converter) { try(InputStream doc=new URL(filePath).openStream();) { File outputFile=File.createTempFile(outFilePath, ".pdf"); OutputStream outputStream = new FileOutputStream(outputFile); //换docx=>pdf converter.convert(doc).as(DocumentType.DOCX).to(outputStream).as(DocumentType.PDF).execute(); doc.close(); outputStream.close(); return outputFile; } catch (Exception e) { e.printStackTrace(); }响应速度还是很慢,在这个代码基础上优化代码,生成完整的优化后的代码
03-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值