2011-03-31 145 views
1

我有這個絕妙的想法來加速生成36個文件所需的時間:使用36個線程!不幸的是,如果我用36個線程/會話啓動一個連接(一個連接對象),那麼與一次執行每個線程相比,所有內容都會更多。
現在,如果我嘗試創建36間新的連接(36個j2ssh連接對象),則每個線程擁有服務器的單獨連接,無論我走出內存異常(不知何故程序仍然運行,併成功結束其工作,執行速度較慢當我執行一個接一個的線程時)。在java中運行多少個線程?

那該怎麼辦?如何找到我應該使用的最佳線程數? 因爲Thread.activeCount()是3開始我的36線程之前?!我正在使用聯想筆記本電腦英特爾酷睿i5。

+0

您是否在服務器或j2ssh連接的客戶端上運行您的工作線程? – 2011-03-31 12:54:26

+0

@PaŭloEbermann在服務器上運行它們,線程==向服務器發送2條命令 – user615927 2011-03-31 13:25:14

+0

聽起來就像您需要查看JVM中是否內存不足。 – 2012-10-01 10:25:36

回答

10

你可以縮小它與ExecutorService更合理的線程數。您可能希望在可用的處理器內核數量附近使用某些東西,G:

int threads = Runtime.getRuntime().availableProcessors(); 
ExecutorService service = Executors.newFixedThreadPool(threads); 
for (int i = 0; i < 36; i++) { 
    service.execute(new Runnable() { 
     public void run() { 
      // do what you need per file here 
     } 
    }); 
} 
service.shutdown(); 
+0

那麼你在這裏看到的完成時間是〜30分鐘我猜想36個操作中的每一個都是一個接一個地創建和執行的,thread1.start; thread1.end; thread2.start; thread2.end..thread36.end ... I個人預計在12分鐘內至少不會超過30,它現在可以提高速度線程數(Executors.newFixedThreadPool(threads); )我設置了4 – user615927 2011-03-31 12:33:17

0

使用比機器上的內核數量多的線程只會減慢整個過程。它會加快,直到你達到這個數字。

+0

所以如果我有4個核心,我相信當時最佳的速度是使用3個線程?至少我已經檢查過(使用幾個命令)這樣的時間:Executors.fixedThreadPool(2)-time 6:40min fixedThreadPool(3)-5:28min。 ThreadPool(4)-9:56分鐘waylonger! ThreadPool(8)-13:13分鐘。無法使用我可以使用的最大線程數是3?! – user615927 2011-03-31 13:06:13

1

蠻力:配置文件增量。逐漸增加線程數量並檢查性能。至於連接的號碼就是36,它應該是很容易

1

你需要明白,如果你創建36個線程你仍然有一個或兩個處理器,它將大部分時間威脅之間進行切換。

我會說你增加線程一點點,讓我們說6,看看行爲。然後從那裏開始

0

確保您不會創建比您擁有處理單元更多的線程,或者您可能會創建更多的開銷,而且上下文切換的開銷將超過併發性。另外請記住,您只有1個硬盤驅動器和1個硬盤驅動器控制器,因此我懷疑多線程會在這裏幫助您。

+0

**請記住,您只有1個硬盤驅動器和1個硬盤驅動器控制器,因此我懷疑多線程會在這裏幫助您。**爲什麼?如果我可以通過膩子打開5個不同的窗口(5個連接到服務器),並執行5個命令組,我應該能夠使用java做同樣的事情?! – user615927 2011-03-31 13:00:37

+0

如果您要在一個系統上創建36個文件,或者您沒有將36個文件連接到單個系統,那麼驅動器併發性可能會成爲一個問題,除非系統正在使用單個HDD以外的存儲系統。你必須想象一個HDD是一個單線程實體,你一次只能寫一個。 – Lazarus 2011-03-31 14:10:22

+0

您需要明白,線程之間的切換不是「免費」,這會花費時間。這只是一小段時間,但當你多次使用36個線程時,每次可能會多次切換上下文,並且該庫可能沒有針對多線程進行大量優化,您所看到的方式會比您想象的要多。線程不是萬能的靈丹妙藥,除非你真的明白髮生了什麼,我建議不要使用它,它就像一把非常鋒利的刀。如果你不知道如何正確使用它,那麼你將會傷害自己。 – Lazarus 2011-03-31 14:17:14

2

您的英特爾i5有兩個內核;超線程使它們看起來像四個。所以你只能得到四個內核的並行化價值;其餘的線程都是時間片。

假設每線程1MB RAM只是創建線程,然後添加每個線程都需要處理的文件的存儲。這會給你一個關於你爲什麼會發生內存錯誤的想法。你正在處理的文件有多大?你可以看到,如果它們很大,同時將它們存儲在內存中,你會遇到問題。

我假設服務器接收的文件可以接受多個連接,所以有在嘗試此值。

我倒是基準1個線程,然後增加他們,直到我發現,性能曲線變平。

+0

好吧,你是對的,serever可以同時進行至少三個命令(甚至可能是36)。所以我打算在thread1,2上同時運行兩個命令,然後在主線程上運行第三個命令?! – user615927 2011-03-31 12:50:24

3

一個好的做法是產生相當於處理器內核數量的線程。我通常使用Executors.fixedThreadPool(numOfCores)執行者服務,並且繼續爲我的工作隊列提供工作,這很簡單。 :-)

1

一種調整方式線程機器的大小numebr是使用

int processors = Runtime.getRuntime().availableProcessors(); 
int threads = processors * N; // N could 1, 2 or more depending on what you are doing. 
ExecutorService es = Executors.newFixedThreadPool(threads); 
1

首先,你必須找出瓶頸是

  • 如果是SSH連接,它通常無助於並行打開多個連接。如果需要,最好在一個連接上使用多個通道。

  • 如果是磁盤IO,創建多個線程寫入(或讀取)僅有助於訪問不同的磁盤(這種情況很少)。但是當你在一個線程中等待磁盤IO時,你可以讓另一個線程執行CPU綁定的事情。

  • 如果是CPU,並且有足夠的空閒內核,則更多的線程可以提供幫助。更甚者,如果他們不需要訪問公共數據。但是,仍然有比線程多的線程(+一些線程在做IO)沒有幫助。 (另外請記住,服務器上通常還有其他進程。)

+0

另一個注意事項:在unix-ish機器上,htop是一個很好的工具請參閱CPU和內存使用情況。 – trillions 2012-08-29 21:37:24