[英]Java: Create large number of Callables or distribute iterator result to threads?
我写了一个操作图像的应用程序。 我的操作代码应该应用于文件夹中的所有图像(每个文件夹最多1百万个)。
到目前为止,对于文件夹中的每个图像,我创建了一个Callable
(它是一个操纵图像的工作者)并将其添加到ArrayList
。 然后我使用FixedThreadPool
的invokeAll
方法来并行化工作。
但是,我的问题是: 这个好设计吗? 我有一些疑问,首先在数组列表中添加1百万个元素真的很有意义。 我正在考虑将iterator
(通过文件)传递给所有线程并让每个线程接受下一个元素并处理它(当然,不幸的是阻塞问题) - 但这有意义吗?
我听起来不错,即使它不一定非常有效并且不能很好地扩展。 另一种设计可能是:
ArrayBlockingQueue<File>
(比如说大两倍) FileVisitor
,我们称之为ImageFileVisitor
,这在visitFile
方法puts
了访问文件中的队列-这是一个阻塞调用,因此将等到队列不满 Callable
S作为您的池的大小,使他们每个人的take
从队列中,做他们必须做的事 注意:线程池的大小应该相当小。 如果您的图像处理非常繁重,请使用大小的处理器数量,如果它有点微不足道并且大部分时间花在读取/写入文件上,请使用较小的大小。
FixedThreadPool
使用LinkedBlockingQueue
的Integer.MAX_VALUE
:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
所以,它的情感非阻塞,就像你能够offer
/ put
百万个Runnable
实例一样,当然,这是为了保存数百万个对象而不记得使用内存,尽管你的fixedPoolSize
相对要小得多,比如5/10。
直接改进这种情况的一种方法是使用具有有限队列大小的FixedThreadPool
:
int nThreads = 10;
int maxQSize = 1000;
ExecutorService service = new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(maxQSize))
通过以上apporach,您的put
期权将阻止Q
1000
runnables,但只要其中一些完成, put
将继续。 通过执行invokeAll
,将有10个正在运行的线程和最多1000个可运行的实例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.