簡體   English   中英

Java:創建大量Callables或將迭代器結果分配給線程?

[英]Java: Create large number of Callables or distribute iterator result to threads?

我寫了一個操作圖像的應用程序。 我的操作代碼應該應用於文件夾中的所有圖像(每個文件夾最多1百萬個)。

到目前為止,對於文件夾中的每個圖像,我創建了一個Callable (它是一個操縱圖像的工作者)並將其添加到ArrayList 然后我使用FixedThreadPoolinvokeAll方法來並行化工作。

但是,我的問題是: 這個好設計嗎? 我有一些疑問,首先在數組列表中添加1百萬個元素真的很有意義。 我正在考慮將iterator (通過文件)傳遞給所有線程並讓每個線程接受下一個元素並處理它(當然,不幸的是阻塞問題) - 但這有意義嗎?

我聽起來不錯,即使它不一定非常有效並且不能很好地擴展。 另一種設計可能是:

  • 創建一個比FixedThreadPool更大的ArrayBlockingQueue<File> (比如說大兩倍)
  • 創建FileVisitor ,我們稱之為ImageFileVisitor ,這在visitFile方法puts了訪問文件中的隊列-這是一個阻塞調用,因此將等到隊列不滿
  • 創造盡可能多Callable S作為您的池的大小,使他們每個人的take從隊列中,做他們必須做的事

注意:線程池的大小應該相當小。 如果您的圖像處理非常繁重,請使用大小的處理器數量,如果它有點微不足道並且大部分時間花在讀取/寫入文件上,請使用較小的大小。

FixedThreadPool使用LinkedBlockingQueueInteger.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM