0

シングルスレッドを使用して一度に1つの画像のみを実行すると、複数ページのTIFF画像を問題なく圧縮できるJavaアプリがあります。ただし、スレッド プールを使用してマルチスレッド化するとすぐに、問題が発生し始めます。たとえば、2 つの TIFF 画像を含むディレクトリがあり、2 つのスレッドでアプリを実行すると、最初の画像は問題なく圧縮され、すべてのページがそこにあります。しかし、2 番目は常に最初のページを除くすべてのページを失います。

ディレクトリから画像の 1 つを削除し (どちらでも構いません)、単一のスレッドで再度実行すると、両方の画像の画像が圧縮され、各画像のページ数が維持されます。

私の圧縮方法は TiffHandler というクラスにあり、具体的な方法は次のとおりです。

public synchronized void compress() throws IOException
{
    System.out.println("NUMpAGES: " + numPages);
    if(this.getSrcImageFile().length()<SIZE_THRESHOLD){
        this.closeAllStreams();
        return;
    }
    this.initOutStreams();
    this.setImageEncoder(ImageCodec.createImageEncoder("tiff", this.getOutputStream(), null));
    int compressionAlgorithm;
    if(bitDepth == 1 || bitDepth == 8)
    {
        /*Cant use JPEG_TTN2 with images that have less than 8-bit samples/only have a bit-depth of 1.*/   
        compressionAlgorithm = TIFFEncodeParam.COMPRESSION_DEFLATE;
        encodeParams.setCompression(compressionAlgorithm); //redundant with line above
    }
    else
    {

        System.out.println("Attempting to compress using JPEG_TTN2 with bit depth: " + bitDepth);
        compressionAlgorithm = TIFFEncodeParam.COMPRESSION_JPEG_TTN2;
        encodeParams.setCompression(compressionAlgorithm); //redundant with line above
    }
    this.setImageEncoder(ImageCodec.createImageEncoder("tiff", this.getOutputStream(), encodeParams));
    Vector vector = new Vector();
    if(numPages == 1){
         for(int i = 0; i < numPages - 1; i ++) //i < bufferedImages.length OLD
         {
              System.out.println(i);
              vector.add((bufferedImages[i]));
         } 
    }else{
         System.out.println("Using second case");
         for(int i = 0; i < numPages; i ++)
         {
              System.out.println("Adding to vector image for file " + this.getSrcImagePath() + " " + i);
              vector.add((bufferedImages[i]));
         }            
    }

    System.out.println("Buffered Images size: " + bufferedImages.length);

    Iterator vecIter = vector.iterator();
    if(numPages > 1){
        vecIter.next();
    }

    encodeParams.setExtraImages(vecIter);
    this.getImageEncoder().encode(bufferedImages[0]);
    closeAllStreams();
}

スレッドを作成して実行する特定のメソッドは次のとおりです。

public void compressImages() throws IOException{

    ExecutorService executor = Executors.newFixedThreadPool(NTHREADS);
    for(int i = 0; i < TIFFList.size(); i ++)
    {
        TiffHandler newTiffHandler = new TiffHandler(TIFFList.get(i).getPath(), TIFFList.get(i).getPath());
        Runnable worker = new ImgCompressor(newTiffHandler);
        executor.execute(worker);
        currCount++;
        if(currCount%2 == 0)
        {
            updateProgress(currCount);
            System.out.println((double)currCount/(double)imageCount);
        }else if(i == TIFFList.size() - 1){
            updateProgress(currCount);
        }

    }
    executor.shutdown();
    try 
    {
        executor.awaitTermination(60, TimeUnit.SECONDS);
    } 
    catch (InterruptedException ex) 
    {
        Logger.getLogger(FJImageCompressor.class.getName()).log(Level.SEVERE, null, ex);
    }finally{
        this.mainProgBar.setString("Complete");
        this.mainProgBar.update(this.mainProgBar.getGraphics());
    }
}

また、重要な場合は、実行可能なクラスを次に示します。

import java.io.*;
public class ImgCompressor implements Runnable {

    private ImageHandler mainHandler;

    public ImgCompressor(ImageHandler mainHandler){
        this.mainHandler = mainHandler;
    }

    @Override
    public void run() {
        try{
            mainHandler.compress();
        }catch(IOException e){
            e.printStackTrace();
        }

    }

}

TiffHandler クラスとそのスーパー ImageHandler クラスのほぼすべてのメソッドがすべて同期されているときに、これらのスレッドが互いに混乱している理由を、私は一生理解できません。

何がこれを引き起こしているのでしょうか?

4

1 に答える 1