我基本上是尝试使用itext将tiff文件转换为pdf,这非常简单。
但是从我所看到的TiffImage.getTiffImage
花费了大量时间来执行更大的文件。
我的要求是使用FutureTask
和ExecutorService
来提供多线程解决方案。这是我目前的代码:
import java.util.concurrent.Callable;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.RandomAccessFileOrArray;
import com.itextpdf.text.pdf.codec.TiffImage;
public class ProcessTiffImage implements Callable<Image>{
RandomAccessFileOrArray tiffFile;
int pageNo;
public ProcessTiffImage(RandomAccessFileOrArray tiffFile, int pageNo){
this.tiffFile = tiffFile;
this.pageNo = pageNo;
}
public Image call() throws Exception {
Image image = TiffImage.getTiffImage(tiffFile, pageNo);
return image;
}
}
并且转换方法是
public boolean convert(Document document) {
int numOfThreads = Runtime.getRuntime().availableProcessors() ;
ExecutorService service = Executors.newFixedThreadPool(numOfThreads );
List<FutureTask<Image>> taskList = new ArrayList<FutureTask<Image>>();
List<Image> imageList = new ArrayList<Image>();
for (int page = 1; page <= numOfPages; page++) {
FutureTask<Image> futureTask = new FutureTask<Image>(new ProcessTiffImage(tiffFile, page));
taskList.add(futureTask);
service.execute(futureTask);
}
try {
// Wait until all results are available
for (FutureTask<Image> future : taskList) {
imageList.add(future.get());
}
} catch (InterruptedException ex) {
ex.printStackTrace();
} catch (ExecutionException ex) {
ex.printStackTrace();
}
service.shutdown();
boolean success = generatePdf(document, imageList);
return success;
}
但我在NullPointerException
获得future.get()
。问题是执行不是等待TiffImage.getTiffImage(tiffFile,pageNo)完成。因此我无法创建图像列表。
非常感谢任何帮助。
堆栈跟踪
java.util.concurrent.ExecutionException: java.lang.NullPointerException
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:188)
at com.app.convertor.TiffParser.convert(TiffParser.java:107)
at com.app.start.TiffToPdf.main(TiffToPdf.java:40)
Caused by: java.lang.NullPointerException
Caused by: java.lang.NullPointerException
at com.itextpdf.text.pdf.codec.TIFFDirectory.getFieldAsLong(TIFFDirectory.java:467)
at com.itextpdf.text.pdf.codec.TIFFDirectory.getFieldAsLong(TIFFDirectory.java:477)
at com.itextpdf.text.pdf.codec.TiffImage.getTiffImage(TiffImage.java:124)
at com.itextpdf.text.pdf.codec.TiffImage.getTiffImage(TiffImage.java:106)
at com.app.processor.ProcessTiffImage.call(ProcessTiffImage.java:20)
at com.app.processor.ProcessTiffImage.call(ProcessTiffImage.java:1)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
答案 0 :(得分:3)
不要自己创建Future
,请执行人为您创建,(即:提交Callable
)
List<Future<Image>> taskList = new ArrayList<Future<Image>>();
for (int page = 1; page <= numOfPages; page++) {
Future<Image> futureTask = service.submit(new ProcessTiffImage(tiffFile, page));
taskList.add(futureTask);
}
for (Future<Image> future : taskList) {
imageList.add(future.get());
}
注意:请考虑改为使用ExecutorCompletionService。
答案 1 :(得分:0)
这似乎正在发生,因为RandomAccessFileOrArray
不是线程安全的。
您在future.get()
调用中遇到的异常是TiffImage.getTiffImage()
调用中的基础异常,这似乎正在发生,因为该方法对传递的TIFF数据不满意。特别是,它正在寻找一些领域,似乎它不存在。可能是图像的高度还是宽度?
但是这种情况正在发生,因为RandomAccessFileOrArray
正在多个线程中使用。每当一个线程移动文件中的指针时,它就会搞砸其他线程正在做的事情。
您需要使用RandomAccessFileOrArray.createView()
来获取要传递给每个线程的文件的新视图:
Image image = TiffImage.getTiffImage(tiffFile.createView(), pageNo);