0

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

我已经读到,ExecutorService当特定页面的 HTTP 请求到达时,我可以使用 an 在新线程中启动/排队图像生成操作。我如何确保我不会排队重复操作(例如,两个用户从同一个 PDF 请求同一个页面)而不求助于单线程执行器?如何使用同步列表之类的东西来跟踪工作线程正在处理的图像(或者,什么类型的同步机制可以帮助我跟踪)?

4

2 回答 2

1

您可以使用ConcurrentSkipListSetConcurrentHashMap来跟踪哪些 PDF 已被处理(并且可能已被缓存)或当前正在被处理。使用ConcurrentLinkedQueue处理您的 PDF 到图像请求;当工作线程从队列中拉出一个请求时,它会将其添加到 Set/Map 中,如果添加成功则线程处理该请求,如果添加失败则该请求已经在容器中。

于 2013-04-14T01:20:22.253 回答
1

您可以使用ConcurrentHashMap<String, Future<String>>带有 PDF 标识符(例如文件路径等)的 a 作为键,并将表示转换操作本身的任务作为值。

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可以在这方面为您提供帮助。

于 2013-04-14T09:31:38.343 回答