我有一个Java 1.5 Web应用程序,可将任意PDF文件转换为图像。一次性处理所有甚至单个PDF的页面都需要很长时间,因此我希望按需处理页面。
我read that I can use an ExecutorService
在特定页面的HTTP请求到达时,在新线程中启动/排队图像生成操作。如何确保我不排队重复操作(例如,两个用户从相同的PDF请求相同的页面)而不诉诸单个线程执行程序?如何使用类似于同步列表的内容来跟踪工作线程正在处理哪些图像(或者,哪种类型的同步机制可以帮助我跟踪这些图像)?
答案 0 :(得分:1)
您可以使用ConcurrentSkipListSet或ConcurrentHashMap来跟踪哪些PDF已处理(并且可能已缓存)或当前正在处理中。使用ConcurrentLinkedQueue来处理PDF到图像的请求;当一个工作线程从队列中提取请求时,它将它添加到Set / Map,如果添加成功,则线程处理请求,如果添加失败,则请求已经在容器中。
答案 1 :(得分:1)
您可以使用带有PDF标识符的ConcurrentHashMap<String, Future<String>>
(例如文件路径左右)作为键,并使用表示转换操作本身作为值的任务。
putIfAbsent
ConcurrentHashMap
方法可以处理比较和设置操作的问题,而isDone
Future
方法可以表明转换是否已经完成。
当putIfAbsent
返回null
时,表示给定PDF的转化任务尚不存在,因此您需要调用ExecutorService.submit(Callable<T> task)
来启动新创建的转化任务;否则,您将省略此步骤并等待已完成的任务完成。
样机:
Future<String> conversionTask = ... // blah
Future<String> existingTask = conversions.putIfAbsent(pdfId, conversionTask);
if (existingTask != null) {
conversionTask = existingTask;
}
// Either way, conversion is scheduled by now.
ExecutorService
负责排队您的转化请求。
转化完成后,您可以通过Future<V>.get()
方法检索结果。
请注意,规范不允许在Java EE应用程序中生成线程。一种常见的方法是将异步处理分离为JMS服务 - Apache Camel可以在这里帮助您