开发者

Why does Java's socket.connect() consume 100% cpu resources?

I created a threadpool and gave it 50 tasks to connect to a server. So once it was done connecting, sending some data over, then disconnecting. It also has a read timeout set at 5 seconds (5000 long of course). I even set the thread pool to a max size of 1. I then fire this up, on linux, and ran htop (a better version of top) to check the CPU usage. I consistently saw one of my cores (2 core machine) at 100% the entire time. I profiled this with hprof (-agentlib:hprof=cpu=samples,interval=20,depth=3) and had socket.connect() at 99%.

Here is what i find weird, isn't the point of blocking IO to block (hence wait) ? My JDK is (from java -version):

Open开发者_如何学CJDK Runtime Environment (IcedTea6 1.6.1) (6b16-1.6.1-3ubuntu3)

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

Update1: this same problem occurs on Sun's JVM too:

java -version
Java version "1.6.0_20"

Update2: This is due to the doConnect method which is native. Anyone know how I can view the source for this native/C code?

Update3: I logged into windows to write the code and test it. It worked fine, no CPU resources being hosed. I log back into linux, and now the problem is still here, but not as sever as to hose the entire CPU core at 100% for just 1 connect.... Here is the code:

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");
    }

}


I just wanted to comment that it looks like you are abusing the thread-pool, since you actually instantiate new objects of type Thread 1500 times, only to pass them to a thread-pool that instantiates more threads in order to run your tasks. What you should normally do is instantiate a Runnable and let the thread-pool do it's job. I'm not saying this is what causes the CPU to choke, but it surly is a problem.


Putting aside the design issues with the code (for example, tasks is never really used), I could not reproduce the high CPU usage on either Windows or Ubuntu (12.04.2 LTS).

Can you please upgrade your JDK to 1.7 (sudo apt-get install openjdk-7-jdk) and let me know which version of the JDK you are using? Mine is javac 1.7.0_25, for example (got using javac -version)

I will try to dig up further after that...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜