我的并行 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 类:
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 公共库(见此处)并找到了一种将图像从一个 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();
}
}
}
}