线程中出现奇怪的 http 超时错误



我正在使用ARIN rest whois服务来查找组织的IP地址列表。 由于列表很长(下面的列表只是一个非常小的子集),我选择使用线程来获得更快的性能。

public class SimpleThreadPool {
    public final static String[] ips = { 
        "192.150.16.64","192.243.232.36","208.77.139.8","63.140.35.160",
        "63.140.35.161","63.140.35.162","63.140.59.142","63.140.61.200",
        "66.235.132.238","66.235.137.133","66.235.138.18","66.235.138.192",
        "66.235.138.195","66.235.139.152","66.235.139.172","66.235.139.204",
        "66.235.139.205","66.235.139.206","66.235.139.227","66.235.141.144",
        "66.235.141.145","66.235.141.146","66.235.141.16","66.235.142.20",
        "66.235.142.24","66.235.141.145","184.106.60.35","207.171.162.26",
        "207.171.162.75","207.171.162.95","207.171.185.201","207.171.187.117",
        "207.171.187.118","207.171.189.80","207.171.189.81","216.137.37.108",
        "216.137.37.122","216.137.37.128","216.137.37.138","216.137.37.140",
        "216.137.37.178","216.137.37.183","216.137.37.198","216.137.37.225",
        "216.137.37.235","216.137.37.37","216.137.37.52","216.137.37.57",
        "216.137.37.6","216.137.37.84" 
    };
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(4);
        for (int i = 0; i < ips.length; i++) {
            Runnable worker = new WorkerThread(ips[i]);
            executor.execute(worker);
        }
        executor.shutdown();
        while (!executor.isTerminated()) {}
        System.out.println("All threads finished.");
    }
}

这是WorkerThread:

public class WorkerThread implements Runnable {
    private String workingIP;
    public WorkerThread(String workingIP) {
        this.workingIP = workingIP;
    }

    @Override
    public void run() {
        try {
            URL url = new URL("http://whois.arin.net/rest/ip/" + workingIP);
            InputStream inputStream = null;
            HttpURLConnection con = (HttpURLConnection)(url.openConnection());
            con.connect();
            inputStream = con.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            String line = null;
            while( (line=br.readLine()) != null )
            {
                if (line.contains("<td>Organization</td><td>")) {
                    String companyName = line.replace("<td>Organization</td><td>", "").trim();
                    System.out.println(workingIP + " maps to: " + companyName);
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在我的工作机器上(带 i5-2400、4GB RAM、32 位 Win7),这段代码一直工作正常,直到数组中的第 45+ 个 IP 地址左右。 然后,我为其余查找抛出java.net.ConnectException错误:

...
216.137.37.57 maps to: Amazon.com, Inc.
216.137.37.6 maps to: Amazon.com, Inc.
java.net.ConnectException: Connection timed out: connect
       at java.net.PlainSocketImpl.socketConnect(Native Method)
       at java.net.PlainSocketImpl.doConnect(Unknown Source)
       at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
       at java.net.PlainSocketImpl.connect(Unknown Source)
       at java.net.SocksSocketImpl.connect(Unknown Source)
       at java.net.Socket.connect(Unknown Source)
       at java.net.Socket.connect(Unknown Source)
       at sun.net.NetworkClient.doConnect(Unknown Source)
       at sun.net.www.http.HttpClient.openServer(Unknown Source)
       at sun.net.www.http.HttpClient.openServer(Unknown Source)
       at sun.net.www.http.HttpClient.<init>(Unknown Source)
       at sun.net.www.http.HttpClient.New(Unknown Source)
       at sun.net.www.http.HttpClient.New(Unknown Source)
       at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(Unknown Source)
       at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
       at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source)

如果我将执行程序的线程池大小更改为 1,那么一切正常并且不会引发任何错误,但显然查找需要更长的时间。

真正奇怪的是,如果我在2011 Core i7 Mac上运行相同的代码,则不会抛出任何错误。 当然,这两者在不同的网络上(我的工作机器使用我工作的网络,而我的Mac无线连接到智能手机)。

知道这里发生了什么,我能做些什么来修复它吗?

您需要编写合理的错误处理代码。真的就是这么简单。如果连接超时,您希望执行什么操作?如果您在慢速网络上一次建立大量连接,其中一些可能会超时。

最新更新