4

我编写了一个应用程序来处理图像。我的操作代码应应用于文件夹中的所有图像(每个文件夹最多 100 万张)。

到目前为止,我为文件夹中的每个图像创建了一个Callable(这是一个操作图像的工作人员)并将其添加到一个ArrayList. 然后我使用invokeAlla 的方法FixedThreadPool来并行化工作。

但是,我的问题是:这是好的设计吗?我怀疑首先向数组列表添加 100 万个元素是否真的有意义。我正在考虑将iterator(通过文件)传递给所有线程,并让每个线程获取下一个元素并处理它(不幸的是,当然存在阻塞问题)-但这有意义吗?

4

2 回答 2

3

我听起来不错,即使它不一定非常有效并且不能很好地扩展。另一种设计可能是:

  • 创建ArrayBlockingQueue<File>比您的 FixedThreadPool 更大的大小(说是两倍大)
  • 创建一个FileVisitor,让我们调用它ImageFileVisitor,它在队列中访问文件的visitFile方法puts中 - 这是一个阻塞调用,因此它将等待队列未满
  • 创建与Callable池大小一样多的 s 并将它们中的每一个take从队列中取出并做他们必须做的事情

注意:线程池的大小应该相当小。如果您的图像处理非常繁重,请使用处理器数量作为大小,如果它有点微不足道并且大部分时间都花在读取/写入文件上,请使用较小的大小。

于 2013-06-03T12:19:19.243 回答
1

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))

使用上述方法,您的put调用将阻止 中的1000可运行对象Q,但一旦其中一些完成,put将继续。通过这样做invokeAll,将有 10 个正在运行的线程和最多 1000 个可运行实例。

于 2013-06-03T12:22:05.677 回答