使用ExecutorService在Java中重命名并行映像:不使用100%的cpu-power

时间:2013-03-01 15:31:15

标签: java multithreading parallel-processing executor

我的并行Java代码存在问题。我尝试从磁盘读取一些图像,更改图像的名称,然后将它们再次保存到不同的文件夹中。 为此,我尝试按如下方式并行运行:

    int nrOfThreads = Runtime.getRuntime().availableProcessors();
    int nrOfImagesPerThread = Math.round(remainingImages.size()/((float)nrOfThreads));

    ExecutorService ex2 = Executors.newFixedThreadPool(nrOfThreads);
    int indexCounter = 0; 
    for(int i = 0; i<  nrOfThreads; ++i) {
        if(i != (nrOfThreads-1)) {
            ex2.execute(new ImageProcessing(remainingImages.subList(indexCounter, indexCounter+nrOfImagesPerThread), newNames.subList(indexCounter,indexCounter+nrOfImagesPerThread))); 
            indexCounter+=nrOfImagesPerThread;
        }else {
            ex2.execute(new ImageProcessing(remainingImages.subList(indexCounter, remainingImages.size()), newNames.subList(indexCounter,remainingImages.size()))); 
        } 
    }


    ex2.shutdown();

    try {
        ex2.awaitTermination(12, TimeUnit.HOURS);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

,这是ImageProcessing-class:

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;

import javax.imageio.ImageIO;

public class ImageProcessing implements Runnable {

private List<String> oldPaths;
private List<String> newPaths;

public ImageProcessing(List<String> oldPaths, List<String> newPaths) {
    this.oldPaths = oldPaths;
    this.newPaths = newPaths;
}

@Override
public void run() { 
    for(int i = 0; i<  oldPaths.size();++i) {
        try {
            BufferedImage img = ImageIO.read(new File(oldPaths.get(i)));
            File output = new File(newPaths.get(i)); 
            ImageIO.write(img, "jpg", output);
        } catch (IOException e) { 
            e.printStackTrace();
        }
    }
}

}

我将for循环中的图像位置划分为(线程数) - 部分,因此在我的情况下大约有8个部分。当我现在运行代码时,它确实并行运行,但它没有利用我100%的CPU功率。它只使用每个处理器的大约25%。

有人知道为什么会发生这种情况吗?或者我只是搞砸了编程中的某个地方?

非常感谢!

编辑:为了完成寻找相同功能的人,我查看了Apache commons库(see here)并找到了一个更好,更快速的方法来复制从一个HDD到另一个HDD的图像。 ImageProcessing类现在看起来如下:

import java.io.File;
import java.io.IOException;
import java.util.List;


import org.apache.commons.io.FileUtils;


public class ImageProcessing implements Runnable {

private List<String> oldPaths;
private List<String> newPaths;

public ImageProcessing(List<String> oldPaths, List<String> newPaths) {
    this.oldPaths = oldPaths;
    this.newPaths = newPaths;
}

@Override
public void run() { 
    for(int i = 0; i<  oldPaths.size();++i) {
        File sourceFile = new File(oldPaths.get(i)); 

        File targetFile = new File(newPaths.get(i)); 
        //copy file from one location to other
        try {
            FileUtils.copyFile(sourceFile, targetFile);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}
}

1 个答案:

答案 0 :(得分:1)

你的问题是,这里的瓶颈肯定是磁盘的I / O. 您可能需要在没有ExecutorService的情况下重命名文件。

换句话说:将更改(重命名文件)写入磁盘消耗的时间比CPU使用的时间长。

你不能多线程这样的行动。

只需测量代码的串行(非多线程)版本所需的时间,并将其与多线程代码所需的时间进行比较。它或多或少都是一样的。