2010-06-05 176 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

我会尝试后进一步挖掘...