2014-01-22 88 views
1

我是線程新手,所以我想了解當您在循環中創建一堆Thread時出現的幕後情況,以及這樣做的意義/更好的方法。在循環上創建線程

下面是一個例子:

for (Page page : book) { 
    Thread t = new Thread(new Runnable() { 
     public void run() { 
      //http request to get page and put into concurrent data structure 
     } 
    }); 
    t.start(); 
    threads.add(t); 
} 
//wait for threads 

正如你很可能會看到,在我的具體使用情況,現在,我通過,我通過HTTP請求對象分頁。我知道這裏不一定需要成爲線程,而是我可以提出異步請求,但是如何(以及解釋)如何改進。

回答

3

在您的示例中,您正在爲書中的每個Page對象創建並啓動一個新線程。如果您的系統上的核心數量多於此核心數量,則此功能無效。

現在直接創建和啓動線程並跟蹤它們也是有點低級的。

更好的解決方案是使用ExecutorService並創建一些線程關閉,例如,系統上存在的內核數量(對於您可能希望創建更多線程的I/O綁定任務:你可以查看下面這個答案的評論)。

例如:

final ExecutorService e = 
    Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); 

for (Page page : book) { 
    e.submit(new Runnable() { 
       //http request to get page and put into concurrent data structure} 
} 

你會那麼等待你的ExecutorService終止其工作。

請注意,根據您從中獲取信息的服務器,您可能需要添加有意的延遲,以免「過度」地摧毀服務器。

某些網站會告訴您您可以多久查詢一次(例如比特幣交換允許每秒查詢一次),並且如果您不尊重延遲,將會禁止您的IP。如果他們發現你的速度過快,其他人不會幹得好,只是簡單地禁止你的IP。

+0

這正是我一直在尋找的建議。非常感謝! – tau

+1

'如果您的系統上的內核數量多於核心數量,這樣做效率不高。' - 你知道線程可能會被網絡綁定並且大部分時間被阻塞? –

+0

是的,但我想了解如何更好地使用線程(正如我在我的帖子中所說的,我寧願用異步請求解決這個特定問題,但它讓我思考如何更有效地管理Java中的線程)。 – tau