业务是这样的:
背景:提供rsf服务
1.先根据图片流,将图片写入到服务端的/dev/shm文件下下面(此路径问服务器端内存目录);
2.利用gm将服务器端的图片锐化并变灰;
3.再利用tesseract将图片识别并形成txt文件;
4.由于图片和txt文件均为临时文件,便利用线程池的方式将临时文件删除
private static final Log logger = LogFactory.getLog(IdentifyImgServiceImpl.class); ExecutorService es = Executors.newSingleThreadExecutor(); class DeleteFile implements Runnable{ //源文件路径 private String originalPath; //锐化变灰后路径 private String sharpenPath; //识别后文本路径 private String resultPath; /** * 删除产生的临时文件 * @param originalPath * @param sharpenPath * @param resultPath */ DeleteFile(String originalPath,String sharpenPath,String resultPath){ this.originalPath = originalPath; this.sharpenPath = sharpenPath; this.resultPath = resultPath; } @Override public void run() { File oFile = new File(this.originalPath); File sFile = new File(this.sharpenPath); File rFile = new File(this.resultPath); if(oFile.exists() && oFile.isFile()){ oFile.delete(); } if(sFile.exists() && sFile.isFile()){ sFile.delete(); } if(rFile.exists() && rFile.isFile()){ rFile.delete(); } } } /** * 识别图片 */ @Override public List<String> identifyImgNum(boolean sharpen,List<byte[]> originalByteList) throws Exception{ long startTime = System.currentTimeMillis(); List<String> reList = new ArrayList<String>(); try { Runtime rt = Runtime.getRuntime(); for (int i = 0; (originalByteList != null && originalByteList.size() > 0) && i < originalByteList.size(); i++) { long beginTime1 = System.currentTimeMillis(); //UUID uuid = UUID.randomUUID(); //String fileName = uuid.toString(); // 获得当前时间 DateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); // 转换为字符串 String formatDate = format.format(new Date()); // 随机生成文件编号 int random = new Random().nextInt(10000); String fileName = new StringBuffer().append(formatDate).append(random).toString(); System.out.println("临时文件名=============" + fileName); String originalPath = "D:/dev/shm/"+fileName+".jpg"; String sharpenPath = "D:/dev/shm/"+fileName+".tif"; String resultPath = "D:/dev/shm/result"+fileName; File originalFile = new File(originalPath); OutputStream out = new FileOutputStream(originalFile); out.write(originalByteList.get(i)); out.flush(); out.close(); Process proc = null; if(sharpen && (originalFile.isFile() && originalFile.exists())){ //锐化并变灰 proc = rt.exec("gm convert -sharpen 10x10 -compress none -depth 8 -colorspace Gray " + originalPath +" "+ sharpenPath); proc.waitFor(); long endTime1 = System.currentTimeMillis(); logger.info("endTime1 - beginTime1=" + (endTime1 - beginTime1)); }else if(originalFile.isFile() && originalFile.exists()){ long endTime2 = System.currentTimeMillis(); //变灰 proc = rt.exec("gm convert -sharpen 10x10 -compress none -depth 8 -colorspace Gray " + originalPath +" "+ sharpenPath); proc.waitFor(); logger.info("endTime2 - beginTime1=" + (endTime2 - beginTime1)); }else{ throw new Exception("源文件读取失败"); } long endTime3 = System.currentTimeMillis(); //识别 logger.info("tesseract "+sharpenPath+" "+resultPath); proc = rt.exec("tesseract "+sharpenPath+" "+resultPath); proc.waitFor(); long endTime4 = System.currentTimeMillis(); logger.info("endTime4 - endTime3=" + (endTime4 - endTime3)); String encoding="GBK"; File inFile=new File(resultPath + ".txt"); if(originalFile.isFile() && originalFile.exists()){ //判断文件是否存在 InputStreamReader read = new InputStreamReader( new FileInputStream(inFile),encoding);//考虑到编码格式 BufferedReader bufferedReader = new BufferedReader(read); String lineTxt = null; while((lineTxt = bufferedReader.readLine()) != null){ if(lineTxt != null && !"".equals(lineTxt)){ reList.add(lineTxt); } } read.close(); long endTime5 = System.currentTimeMillis(); logger.info("endTime5 - endTime4=" + (endTime5 - endTime4)); //提交给多线程 long endTime6 = System.currentTimeMillis(); es.submit(new DeleteFile(originalPath,sharpenPath,resultPath + ".txt")); long endTime7 = System.currentTimeMillis(); logger.info("endTime7 - endTime6=" + (endTime7 - endTime6)); }else{ throw new Exception("找不到指定文件"); } } } catch (Exception e) { logger.error("IdentifyImgServiceImpl:identifyImgNum()", e); } long endTime = System.currentTimeMillis(); logger.fatal("IdentifyImgServiceImpl identifyImgNum() cost time:" + (endTime - startTime)); return reList; }
线程池的引入,提高了性能
|
分享到:
相关推荐
4. **线程池(Thread Pool)**: 线程池是并发编程中的重要概念,它提高了多线程环境下的性能和资源管理。Java通过`java.util.concurrent.ExecutorService`接口和`java.util.concurrent.ThreadPoolExecutor`类提供了...
为了解决这个问题,我们可以使用对象池技术来实现 FTPClient 对象的复用。对象池是一种机制,可以管理对象池中对象的生命周期,提供了获取和释放对象的方法,让客户端可以方便地使用对象池中的对象。 在 Spring ...
为了解决这个问题,Node.js 10.5.0版本引入了worker_threads模块,允许开发者利用多核处理器的优势,通过工作线程(Worker Threads)进行并行计算。 "worker-threads-pool" 是一个专门为Node.js设计的库,它的目的...
线程池技术是现代软件设计中的一项关键技术,它主要用来解决线程创建和销毁的开销问题,同时也能有效解决系统资源不足的问题。服务器软件在处理多任务时,频繁地创建和销毁线程会消耗大量的系统资源并降低程序效率。...
MySQL线程池的引入主要是为了解决“每个连接一个线程”模式下的问题,这种模式在处理大量并发连接时可能导致资源浪费和性能瓶颈。Oracle和MariaDB都提供了线程池解决方案,其中Percona移植并优化了MariaDB的线程池...
为了解决这个问题,引入了**线程池**的概念。 #### 二、线程池的概念 线程池是一种设计模式,它通过预先创建一定数量的线程来提高程序的响应速度和效率。当有任务需要执行时,线程池分配一个空闲线程来处理这个任务...
线程池是管理线程的一种机制,它的引入解决了频繁创建和销毁线程带来的开销。使用线程池可以减少内存消耗,降低系统启动新线程的延迟,以及提高系统稳定性,防止因过度创建线程导致的OOM异常。Java提供了Executors...
线程池的引入解决了这个问题,将这些阻塞任务分配给线程池中的其他线程,让主工作线程可以继续处理其他事件。 例如,当 Nginx 需要从硬盘读取一个大文件时,如果使用传统的同步方式,整个事件循环会暂停直到文件...
在这个主题中,我们将深入探讨如何利用Spring MVC与Spring线程池来有效地管理并发请求,并解决数据同步控制问题。 一、Spring MVC与并发处理 1. Spring MVC通过DispatcherServlet接收HTTP请求,然后根据映射规则将...
【Linux环境下的通用线程池设计】主要关注的是在Linux操作系统中如何高效地处理并发请求,以提升服务器的性能和稳定性。线程池是一种优化并发处理的策略,它旨在解决多进程/线程模型和多路复用I/O模型的不足。 1. *...
为了高效地处理这些请求,引入线程池机制是一种常见的解决方案。 #### 二、传统多线程方案的问题 在传统的多线程服务器模型中,每当有新请求到达时,就会创建一个新的线程来处理这个请求。一旦请求处理完成,线程...
在2012年,AliSQL 5.5版本发布,引入了性能增强和 BugFix 功能,提高了数据库的性能和稳定性。 在2014年,AliSQL 5.6版本发布,引入了 Semi-Sync 机制,提高了数据库的高可用性和可靠性。 在性能优化方面,AliSQL ...
为了解决这些问题,引入了线程池的概念,Socket线程池是这个概念的一个具体应用。 线程池的核心组件包括: 1. **线程池**:一个线程集合,用于存储和管理已创建但当前未执行任务的线程。在示例代码中,`pool`是一...
为了解决这些问题,引入了线程池的概念。线程池是一种用于管理线程的技术,它能够有效地复用预先创建的线程,避免频繁创建和销毁线程所带来的开销,并能控制同时运行的线程数量,防止过多线程导致系统资源耗尽。 ##...
通过上述分析可以看出,基于线程池技术的文件传输模型不仅解决了传统文件传输模型中存在的问题,还为提高文件传输效率提供了一种有效的解决方案。这对于当前高性能计算和大规模数据处理的需求具有重要意义。
线程池的引入正是为了解决这一问题。线程池允许预先创建一定数量的线程,并在任务到来时将任务分配给这些线程,而不需要在每个任务到来时都创建和销毁线程。这样可以显著降低线程创建和销毁的开销,从而提高整体的...
它能够显著减少线程创建和销毁带来的开销,并有助于解决系统资源不足的问题。本文将详细介绍线程池技术的基本原理、优势以及其实现方式,并探讨其在工作流引擎中的具体应用案例。 #### 1. 线程池技术的优点 线程池...
通过监控,我们可以实时了解ClickHouse的运行状况,及时发现并解决问题。 4. **线程池的使用**: 在高并发场景下,合理使用线程池能有效控制并发量,避免线程数量过多导致系统资源耗尽。线程池的配置需要考虑系统...
总的来说,这个资源为学习和实践C++线程池提供了丰富的素材,无论是对C++的旧版本还是新版本,都可以深入理解线程池的设计原理和实现技巧,同时也能了解到多线程编程中的挑战和解决方案。通过对这些源码的分析,...
为了解决上述问题,自适应线程池技术引入了对象池模式的思想,通过动态调整线程池中的线程数量来更好地匹配系统的实际需求。具体来说: 1. **动态预测机制**:利用灰色系统理论等预测算法来预测未来一段时间内所需...