在我的程序中,我有一个while循环,它遍历一堆图片的数组列表,并对它们进行一系列处理,以改变它们的外观和图像类型,然后将它们写入磁盘。我的问题是添加多个线程来处理图像或保存图像加快速度,如果是这样,最好的方法是什么。 ArrayList images = new ArrayList(); //超过500个图像 ArrayList paths = new ArrayList(); int len = images.size();
for (int i =0; i < len ; i ++)
{
BufferedImage image = process (images.get(i))//takes about a second
ImageIO.write(image, "jpg", new File(getImagePaths().get(i)));
}
答案 0 :(得分:3)
您可以将列表划分为n个块,以便您拥有list / n大小的块,然后您可以在这些“块”图像上运行n个线程。通过这种方式,您可以同时完成更多工作。
为了解决一些问题,它很可能会增加I / O并发性,因为在单线程运行中它会在第一次未命中和阻塞时出错,然后再次出错以读取第二个图像等等...在多线程方式中,它将一次阻止n个图像,这允许I / O调度器一次处理更多I / O(这通常是一件好事)。这意味着即使在单核处理器中性能也会提高,这是因为I / O的重叠以及在I / O线程被阻塞等待时在核心上运行的线程数量更多的可用性。
答案 1 :(得分:2)
是的,很有可能因为:
1)您的计算机可能有2到4个CPU或核心
2)图像处理通常是CPU密集型的
3)因此,大CPU负载可以分成多个同时运行的任务。
这总是有效吗?
没有。如果您的进程是i / o(互联网,磁盘或内存)有界(例如,它需要每个映像2G的内存,或者它必须编写大量的临时文件),您将看不到线性加速 - 因为CPU速度的增加将被执行i / o的时间所抵消,这将使您的程序变慢,无论您需要多少处理器来共享图像处理的负载。 就像煮面条一样 - 煮面条需要10分钟。即使你有8个不同的燃烧器同时进行 - 吸入面条的水仍然需要10分钟,所以不会有帮助。
Psuedo代码:
//just a reminder !
public static final int MAX_SEM=8;
processAll()
{
//create a new semaphore with 4 slots.
semaphore = new Semaphore(MAX_SEM) ;
while(! images.empty())
if(semaphore has a slot)
Image img=images.pop();
sempahore.decrement()
Thread().run( new Runable() { public void run() {process(img);} }
else
Thread.sleep(1000);
}
process(Image i)
{ do some work on i
semaphore.increment()
}