跟踪Java Web应用程序中的并发文件处理

时间:2013-04-14 01:12:40

标签: java multithreading web-applications concurrency executorservice

我有一个Java 1.5 Web应用程序,可将任意PDF文件转换为图像。一次性处理所有甚至单个PDF的页面都需要很长时间,因此我希望按需处理页面。

read that I can use an ExecutorService在特定页面的HTTP请求到达时,在新线程中启动/排队图像生成操作。如何确保我不排队重复操作(例如,两个用户从相同的PDF请求相同的页面)而不诉诸单个线程执行程序?如何使用类似于同步列表的内容来跟踪工作线程正在处理哪些图像(或者,哪种类型的同步机制可以帮助我跟踪这些图像)?

2 个答案:

答案 0 :(得分:1)

您可以使用ConcurrentSkipListSetConcurrentHashMap来跟踪哪些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可以在这里帮助您