还是说到前面那篇使用 JAVA 使用 pdfbox实现打印 PDF 文件,使用 pdfbox调用 pdf是可以进行打印的,我在本地电脑进行打印的时候是对的,那是因为,我本地电脑是连接过打印机的,所以当然是可以进行打印文件的,那如果部署到服务器上面,老是会报,未连接打印机的问题,然后我查询了很多的资料,都没有找到答案,有的说服务器上面要安装打印机连接工具才可以,那肯定是不可以的,因为我们做的功能不能说我们知道客户的打印是叫啥然后去连接,既然服务端无法识别,那我还是只能用客户端去实现了,这里我想到的方法就是,批量生成多个pdf文件,然后把这些文件都放入到一个文件中,然后在页面中预览,在进行打印这样就可以实现了,因为我还没找到服务端去进行打印的例子如果有,请告诉我一下谢谢,我也可以去学习下,接下来就去看看代码吧:

        long startTime = System.currentTimeMillis();    //获取开始时间ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2,10,1L,TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(3), Executors.defaultThreadFactory(),new ThreadPoolExecutor.DiscardOldestPolicy());//定义线程池List<Future<String> > arrayList = new ArrayList<>(); //用于接受线程执行的返回值//生成pdf 签章:String[] split = batchId.split(",");for(int i=0;i<split.length;i++){arrayList.add(threadPool.submit(new CarPdfCallable(orderService, propertiesUtil, split[i], templateId,zjl, cw, hg, zb))); //这里去执行生成pdf 签章的方法}CopyOnWriteArrayList<String> copyOnWriteArrayList = new CopyOnWriteArrayList(); //使用并发list去接受值,这里我怕值会乱所以用了并发的listString contractId = StringUtils.randomUUID();//生成新的pdf文件的名字for(int i=0;i<arrayList.size();i++){if(StringUtils.isNotEmpty(arrayList.get(i).get())){copyOnWriteArrayList.add(propertiesUtil.getString("fadada.temp.path")+arrayList.get(i).get());//获取放回值}}String[] objects=copyOnWriteArrayList.toArray(new String[copyOnWriteArrayList.size()]); //转换成数组String filePatch = contractId + ".pdf";boolean b = mergePdfFiles(objects, propertiesUtil.getString("fadada.temp.path")+"pdf\\" +filePatch); //多个pdf写入到一个新的pdf文件中if(b){model.addAttribute("filePatch",filePatch);}long endTime = System.currentTimeMillis();    //获取结束时间System.err.println("程序运行时间:" + (endTime - startTime) + "ms");    //输出程序运行时间 计算程序运行的时间

这里其实是有一个问题,大家有没有注意到一点,为啥获取值要这么麻烦,为啥不在第一个循环中调用?其实这里是个坑,之前我的写法是这样的

for(int i=0;i<split.length;i++){Future<String> arrayList= threadPool.submit(new CarPdfCallable(orderService, propertiesUtil, split[i], templateId,zjl, cw, hg, zb))arrayList.get();}

这里看似是没有问题,但是运行后我发现很慢,并且页面直接说504,浏览器请求超时,然后就在程序还是一直在运行,并且是一个一个生成文件,这是为什么?
不是多线程执行程序,后来查询资料才发现 arrayList.get();这个方法是线程阻塞的,如果直接写在里面就变的和一个一个执行的一样的了,所以这个方法不能这样去写。
CarPdfCallable


/*** @author qrn* @version 1.0* @date 2020/6/4 16:29*/
public class CarPdfCallable  implements Callable<String> {IOrderService orderService;PropertiesUtil propertiesUtil = PropertiesUtil.create("common.properties");/*** 批次Id*/private String batchId;/*** 模板Id*/private String templateId;private String zjl;private String cw;private String hg;private String zb;public CarPdfCallable(IOrderService orderService, PropertiesUtil propertiesUtil, String batchId, String templateId, String zjl, String cw, String hg, String zb) {this.orderService = orderService;this.propertiesUtil = propertiesUtil;this.batchId = batchId;this.templateId = templateId;this.zjl = zjl;this.cw = cw;this.hg = hg;this.zb = zb;}@Overridepublic String call() throws Exception {String file = "";String filePatch = orderService.signOrderPayment(batchId, templateId, "","",zjl,cw,hg,zb);if(StringUtils.isNotEmpty(filePatch)){
//            copyOnWriteArrayList.add(propertiesUtil.getString("fadada.temp.path")+filePatch);file = filePatch;}return file;}
}

这里实现了Callable,这个是多线程执行时,异步返回返回值。里面只有一个方法就是生成pdf文件,然后返回文件名字,用于写入到一个新的文件中

mergePdfFiles方法:

public static boolean mergePdfFiles(String[] files, String newfile) {boolean retValue = false;Document document = null;try {File file = new File(newfile);if(!file.exists()){file.createNewFile();}document = new Document(new PdfReader(files[0]).getPageSize(1));PdfCopy copy = new PdfCopy(document, new FileOutputStream(file.getPath()));document.open();for (int i = 0; i < files.length; i++) {PdfReader reader = new PdfReader(files[i]);int n = reader.getNumberOfPages();for (int j = 1; j <= n; j++) {document.newPage();PdfImportedPage page = copy.getImportedPage(reader, j);copy.addPage(page);}}retValue = true;} catch (Exception e) {System.out.println(e);} finally {System.out.println("执行结束");document.close();}return retValue;}

这样子在不出问题的情况下,我把所有pdf文件写入到一个pdf文件中,然后在页面中展示,直接用pdf自带的浏览器打印就很好的实现这个问题。好了这个问题记录下来,希望对有需要的朋友有帮助。

JAVA 实现批量PDF 打印,线程池多线程执行(附完整代码)相关推荐

  1. JAVA编码(41)—— 线程池队列执行任务(ThreadPoolQueue)(1)

    废话少说,上代码 package com.sinosoft;import java.util.concurrent.*;/*** Created by xushuyi on 2017/4/9.*/ p ...

  2. python使用线程池多线程执行,并得到返回的结果

    多线程的使用场景比如:频繁数据库连接,频繁的资源读取(如频繁读文件.玩命读kafka什么的) 多线程:适合IO密集型 多进程:适合计算密集型 使用线程池的好处是自动管理线程,不会导致线程资源浪费和代码 ...

  3. java 实现秒抢_Java实现抢红包算法,附完整代码(公平版和手速版)

    当我们在群里抢红包时真的是手速越快红包金额越大吗? 当我们在群里抢红包时真的是手速越快红包金额越大吗? 答案当然是并不是,都说了是拼手气,岂能是拼手速! 不过也可以有拼手速的方法 二倍均值法(公平版) ...

  4. java实现qq抢红包_Java实现抢红包算法,附完整代码(公平版和手速版)

    当我们在群里抢红包时真的是手速越快红包金额越大吗? 当我们在群里抢红包时真的是手速越快红包金额越大吗? 答案当然是并不是,都说了是拼手气,岂能是拼手速! 不过也可以有拼手速的方法 二倍均值法(公平版) ...

  5. 如何判断线程池已经执行完所有任务了?

    作者 | 磊哥 来源 | Java面试真题解析(ID:aimianshi666) 转载请联系授权(微信ID:GG_Stone) 很多场景下,我们需要等待线程池的所有任务都执行完,然后再进行下一步操作. ...

  6. JAVA 多线程 JAVA 如何开发一个自定义线程池

    1.多线程设计介绍 每一个线程的启动和结束都是比较消耗时间和占用资源的. 如果在系统中用到了很多的线程,大量的启动和结束动作会导致系统的性能变卡,响应变慢. 为了解决这个问题,引入线程池这种设计思想. ...

  7. java线程池多线程优先级_Java线程优先级

    java线程池多线程优先级 Priority of a thread describes how early it gets execution and selected by the thread ...

  8. java——自己实现基础的线程池及带有任务数过多拒绝策略、线程池销毁、自动扩充线程数量及闲时自动回收线程等操作的改进版线程池

    1. 实现第一版基础的线程池 1.1 首先我们定义一个线程池类ThreadPool,然后线程池有一个容器存放我们创建的线程,另一个容器则是存放当前线程池需要处理的任务队列,线程容器用ArrayList ...

  9. Java 线程池详解及实例代码

    转载自  Java 线程池详解及实例代码 这篇文章主要介绍了Java 线程池的相关资料,并符实例代码,帮助大家学习参考,需要的朋友可以参考下 线程池的技术背景 在面向对象编程中,创建和销毁对象是很费时 ...

  10. java线程池延期执行一次_Java使用者的延期执行

    java线程池延期执行一次 在前面的博客文章(" 延迟执行Java的供应商 "),我引用礁HORSTMANN的陈述书中' 的Java SE8为真的很急关于lambda表达式','所 ...

最新文章

  1. PC软件/web网站/小程序/手机APP产品如何增加个人收款接口
  2. Python(39)_选出列表中的大于66的数字放在字典中
  3. pdo 连接数据库 报错 could not find driver 解决方法
  4. delphi7 中文注释字体_使用nerd-font/font-patcher为字体添加字体图标
  5. 【剑指offer】面试题22:链表中倒数第 K 个节点
  6. virtualbox 启动时报Kernel driver not installed (rc=-1908) 的错误
  7. 美式桌球游戏 开源_开源工具,可将英译为美式英语
  8. Selenium 特点
  9. 浅析C#中的文件操作
  10. 如果粒子运动只受力影响,那么意识从何而来
  11. 网页自动关机代码HTML,电脑怎么设置自动关机时间
  12. 【附源码】计算机毕业设计SSM小区宠物管理系统
  13. 使用redis做缓存处理时出现的问题
  14. java项目实现html转pdf的需求(支持中文和CSS样式)
  15. 使用 ASP.NET 制作一个音乐网站
  16. lamp mysql 密码_lamp 如何修改mysql密码
  17. 【送书活动第二话】:共10本技术书籍送! 送!! 送!!!
  18. Matlab用三种格式来表示日期与时间
  19. 盘点老外对女人的爆笑称呼
  20. windows脚本创建桌面快捷图标方式

热门文章

  1. Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8
  2. FFMpeg无损合并视频的多种方法
  3. 2022-2028年中国罐头行业市场专项调研及发展策略分析报告
  4. RJ45布线 568A 和568B布线标准
  5. easyscreen调用html,840D——EasyScreen输入密码跳转界面的编写-工业支持中心-西门子中国...
  6. Python爬取必应壁纸
  7. Android获取外网ip
  8. Python 查找算法_众里寻他千百度,蓦然回首那人却在灯火阑珊处(线性、二分,分块、插值查找算法)
  9. 【AAAI-2019】论文整理(清单)
  10. 阿里云ACA试题——云安全