これが私の苦境の簡単な要約です。私はマルチスレッドを学んでいるので、約 300 枚の画像を処理するサムネイル作成プログラムを作成することにしました。最初は、すべてのサムネイル作成を 1 つのスレッドで行ったところ、約 99 秒かかりました。だから私は、を使用newFixedThreadPool()
するとプログラムが高速になると考えました。Executors.newFixedThreadPool()
スレッドを手動で作成するよりも、使用する方が安価であると聞いたことがあります。だから私はした:
ExecutorService executor = Executors.newFixedThreadPool(4);
4 は私のマシンのコア数です。
奇妙なことに、これを行うとプログラムが遅くなります。で 1 つのスレッドを使用したnewFixedThreadPool
場合、タスクは約 118 秒で完了しました。4 スレッドを使用した場合、タスクは約 99 秒で完了しました。最初のシングル スレッド操作よりも数ミリ秒遅くなります。10 スレッド使用した場合、所要時間は約 110 秒でした。
プログラムを高速化する方法がまったくわかりません。4 つのスレッドを使用するのが最適であり、シングル スレッド操作の約 4 分の 1 の時間で作業を完了できると考えていました。
何ができるかについて何か提案はありますか?これが私の(非常に醜いコードです)
public class Thumbnails {
protected static BufferedImage image = null;
protected static BufferedImage outBM;
protected static Graphics2D g2d;
public static void main(String[] args) {
long start = System.currentTimeMillis();
File f = new File("/home/njengah/Media/Images");
File[] myPics = f.listFiles();// list of all images folder
ExecutorService executor = Executors.newFixedThreadPool(4);
for (int i = 0; i < myPics.length; i++) {
executor.submit(new Thumbnails().new ImgProcessor(myPics[i]));
}
System.out.println(" all tasks submitted ");
executor.shutdown();
try {
executor.awaitTermination(1, TimeUnit.HOURS);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println(" image processing completed.");
long stop = System.currentTimeMillis();
System.out.println("time taken to process all images: "+(stop - start));
}
// this handles the processing of a single image
protected static void singleImageProcessor(File onePic) throws IOException {
image = ImageIO.read(onePic);
outBM = new BufferedImage((int) (image.getWidth() * 0.1), (int) (image.getHeight() * 0.1), image.getType());
g2d = outBM.createGraphics();
g2d.drawImage(image, 0, 0, (int) (image.getWidth() * 0.1), (int) (image.getHeight() * 0.1), null);
g2d.dispose();
ImageIO.write(outBM, onePic.getName().split("\\.")[1], new File("/home/njengah/Downloads/resized/" + onePic.getName()));
}
private class ImgProcessor implements Runnable {
File onePic;
public ImgProcessor(File onePic) {
this.onePic = onePic;
}
@Override
public void run() {
// this runs one task
System.out.println("starting");
try {
singleImageProcessor(onePic); // single task
} catch (Exception e) {
e.printStackTrace();
} // to make it shut up
System.out.println("finished");
}
}
}