为啥Java的socket.connect()会消耗100%的cpu资源?
Posted
技术标签:
【中文标题】为啥Java的socket.connect()会消耗100%的cpu资源?【英文标题】:Why does Java's socket.connect() consume 100% cpu resources?为什么Java的socket.connect()会消耗100%的cpu资源? 【发布时间】:2010-06-05 00:52:52 【问题描述】:我创建了一个线程池,并为其分配了 50 个任务以连接到服务器。因此,一旦完成连接,发送一些数据,然后断开连接。它还将读取超时设置为 5 秒(当然长 5000 秒)。我什至将线程池的最大大小设置为 1。然后我在 linux 上启动它,并运行 htop(一个更好的 top 版本)来检查 CPU 使用率。我始终以 100% 的速度看到我的一个内核(2 核机器)。我用 hprof (-agentlib:hprof=cpu=samples,interval=20,depth=3
) 对此进行了分析,并且 socket.connect() 达到了 99%。
这就是我觉得奇怪的地方,阻塞 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,现在问题仍然存在,但还不如仅 1 次连接就以 100% 的速度将整个 CPU 内核软管...。这是代码:
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");
【问题讨论】:
代码里肯定有东西,你能把相关的部分贴出来。您可能需要考虑到给您带来问题的最少代码量。 见更新2。它发生在 PlainSocketImpl 内部的 doConnect 方法中。这就是被灌输的东西。我没有任何方法会占用 CPU ..... 1500 个线程,你一定是在开玩笑吧?你怎么知道是连接?无论如何,做 1500 次会占用大量资源。如果您正在寻找 1500 个并发连接,那么您最好获得比您编写的更强大的东西。 @Romain Hippeau:“我什至将线程池设置为最大大小 1” 【参考方案1】:我只是想评论一下,您似乎在滥用线程池,因为您实际上实例化了 Thread 类型的新对象 1500 次,只是为了将它们传递给实例化更多线程的线程池,以便运行您的任务。您通常应该做的是实例化一个 Runnable 并让线程池完成它的工作。我并不是说这是导致 CPU 阻塞的原因,但这确实是个问题。
【讨论】:
我觉得这里可以忽略线程池。我不应该在代码中提交带有该示例的示例,因为它不相关,我对此很懒惰。【参考方案2】:抛开代码的设计问题(例如,tasks
从未真正使用过),我无法在 Windows 或 Ubuntu (12.04.2 LTS
) 上重现高 CPU 使用率。
能否请将您的 JDK
升级到 1.7 (sudo apt-get install openjdk-7-jdk
) 并告诉我您使用的是哪个版本的 JDK
?我的是javac 1.7.0_25
,例如(使用javac -version
)
在那之后我会尝试进一步挖掘......
【讨论】:
以上是关于为啥Java的socket.connect()会消耗100%的cpu资源?的主要内容,如果未能解决你的问题,请参考以下文章