你真的不需要那麼多線程。磁盤只能支持其最大讀寫吞吐量,如果單個線程專用於IO即讀取或寫入,則該線程可輕鬆實現最大化。你也不能同時讀寫硬盤(雖然操作系統緩存層等很複雜),所以併發線程的讀寫操作可能會產生相反的效果。對於非IO任務,擁有比processor \ cores更多的線程也很少,因爲任何其他線程將花費大量時間等待覈心變得可用,例如,如果您有50個線程和4個內核,則在任何給定時間至少有46個線程將處於空閒狀態。浪費的線程將有助於內存消耗也會導致性能開銷,因爲它們都將爭取在某個時間在覈心上獲得破解,而操作系統必須仲裁這場爭鬥。
更簡單的方法是讓一個線程的工作是讀取文件,然後將數據添加到阻塞隊列(例如參見ConcurrentQueue),同時有一些工作線程正在等待文件數據在隊列中(例如,一個數字線程等於處理器\核心的數量)。這些工作線程會在添加項目時穿過隊列,並在空時阻塞。當工作線程完成一項工作時,它可以將其添加到由讀線程線程或專用寫線程監視的另一個阻塞隊列。它的工作是將文件寫出。
此模式旨在平衡IO和CPU之間的一小部分協作線程,其中IO線程的數量被限制爲物理上能夠被硬盤驅動器的數量,以及多個CPU工作線程對您擁有的處理器\核心數量合理。從本質上講,它將IO和CPU分開,以使事情更可預測。
此外,如果IO真的是問題(而不是大量的線程都相互爭鬥),那麼你可以在你的文件讀寫線程中放置一些暫停(例如Thread.Sleep)來限制他們做了很多工作。
更新
或許爲什麼有擺在首位產生這麼多線程有必要解釋。這是線程池使用的退化情況,並且圍繞排隊具有IO組件的工作項。
線程池從其隊列中執行工作項並監視執行工作項目執行的時間。如果當前正在執行的工作項目需要很長時間才能完成(我認爲內存只有半秒),那麼它將開始向池中添加更多線程,因爲它認爲這將更快更公平地處理隊列。但是,如果附加的併發工作項也在共享磁盤上執行工作IO,那麼磁盤的性能實際上會降低,這意味着工作項需要更長的時間才能執行。由於工作項目執行時間較長,線程池會添加更多線程。這是退化情況,隨着更多線程的添加,性能越來越差。
建議使用信號量必須小心,因爲信號量可能會導致線程池線程阻塞,線程池會看到工作項需要很長時間才能執行,並且它仍然會開始添加更多線程。
你說「這些文件正在如此迅速地準備就緒,它佔用了用戶界面」。每次文件準備就緒時,UI是否更新?如果是這樣,這可能是真正的問題嗎? – 2010-08-04 17:42:35