2010-06-05 98 views
4

我創建了一個線程池,併爲它提供了50個任務來連接到服務器。所以一旦完成連接,發送一些數據,然後斷開連接。它也有一個讀取超時設置爲5秒(當然是5000長)。我甚至將線程池設置爲最大大小1.然後,我在linux上啓動它,並運行htop(top的更好的版本)來檢查CPU使用情況。我始終在100%的時間內看到我的一個核心(2核心機器)。我使用hprof(-agentlib:hprof=cpu=samples,interval=20,depth=3)對它進行了描述,並且使用99.%的socket.connect()。爲什麼Java的socket.connect()消耗100%cpu資源?

這裏是我發現很奇怪,是不是阻止IO阻止點(因此等待)?我的JDK是(從java -version):

OpenJDK Runtime Environment (IcedTea6 1.6.1) (6b16-1.6.1-3ubuntu3)

OpenJDK Server VM (build 14.0-b16, mixed mode)

UPDATE1:Sun的JVM會發生同樣的問題太多:

java -version 
Java version "1.6.0_20" 

UPDATE2:這是由於本地的doConnect方法。任何人都知道我可以如何查看本機/ C代碼的來源?

Update3:我登錄到Windows編寫代碼並測試它。它運行良好,沒有CPU資源被洗淨。我重新登錄到Linux和現在的問題是還在這裏,但不作爲服務器作爲軟管整個CPU核心在100%的僅有1連接....下面是代碼:

import java.io.IOException; 
import java.net.InetAddress; 
import java.net.InetSocketAddress; 
import java.net.Socket; 
import java.net.UnknownHostException; 
import java.util.Vector; 
import java.util.concurrent.Callable; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ThreadPoolExecutor; 
import java.util.concurrent.TimeUnit; 


public class SocketTest { 


    public static void main(String[] args) { 
     new SocketTest(); 

    } 

    public SocketTest() { 

     ThreadPoolExecutor tpe = (ThreadPoolExecutor) Executors.newFixedThreadPool(40); 

     Vector<Callable<Object>> tasks = new Vector<Callable<Object>>(); 

     for (int i = 0; i < 1500; i++) 
      tpe.submit(new Thread() { 

       public void run() { 
        byte[] ip = { 74, 125, 19, (byte)((Math.random()*253)+1)}; 
        Socket socket = new Socket(); 
        try { 
         System.out.println("new thread: "+ip[3]); 
         socket.connect(new InetSocketAddress(InetAddress.getByAddress(ip), 80), 3000); 
         socket.close(); 
        } catch (UnknownHostException e) { 
         e.printStackTrace(); 
        } catch (IOException e) { 
         //no need to print 
        } 
       } 
      }); 

      try { 
       tpe.invokeAll(tasks); 
      } catch (InterruptedException e1) { 
       e1.printStackTrace(); 
      } 
      System.out.println("test"); 
      try { 
       //too lazy to write actual code to wait for task completness... 
       tpe.awaitTermination(9001, TimeUnit.DAYS); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      System.out.println("test2"); 
    } 

} 
+1

有任何代碼向我們展示? – 2010-06-05 01:08:23

+0

代碼中必須有東西,你可以發佈相關的部分。您可能需要分解出導致問題的最低代碼量。 – 2010-06-05 02:51:51

+0

請參閱update2。它出現在PlainSocketImpl的doConnect方法中。這就是變得虛弱。沒有任何方法可以讓我吃掉CPU ...... – Zombies 2010-06-05 03:07:12

回答

0

我只是因爲你實際上實例化了類型爲線程1500次的新對象,只是爲了將它們傳遞給爲了運行任務而實例化更多線程的線程池,因此您想評論它看起來像濫用線程池。你通常應該做的是實例化一個Runnable,讓線程池做它的工作。我並不是說這是導致CPU窒息的原因,但這顯然是一個問題。

+0

我認爲這裏可以忽略線程池。我不應該在代碼中提交一個例子,因爲它不相關,我只是懶惰的。 – Zombies 2011-06-10 15:27:00

0

不考慮設計問題與代碼(例如,tasks從來沒有真正使用過),我無法在Windows或Ubuntu(12.04.2 LTS)上重現高CPU使用率。

您能否將您的JDK升級到1.7(sudo apt-get install openjdk-7-jdk)並告訴我您正在使用哪個版本的JDK?我的是javac 1.7.0_25,例如(GOT使用javac -version

我會嘗試後進一步挖掘...