用于读取多个URL的Java循环正在减慢

时间:2014-03-26 02:45:48

标签: java

我已经编写了一些代码来梳理网站上大约10000个网页,以便在网站上整理用户人口统计信息。该程序的基础是读取网站源代码的每一行,解析出所需的数据,然后转到下一页。

我遇到的问题是大约在第650页左右,程序从每秒3页读取到每10-15秒1页。它总是发生在程序执行的同一点。我开始想知道这可能是我的程序的内存问题,并开始检查它的每个方面。最终我把程序剥离了它的基础:

步骤1)创建一个URL对象数组。

步骤2)循环遍历数组并打开/关闭缓冲读取器以读取每一行。

步骤3)阅读整个页面并转到下一行。

即使这在确切的位置放慢了速度,所以这对我正在解析的数据或我存储的数据不是问题。这是以某种方式循环的结果。我想知道我写的内容是否存在导致问题的内存问题?否则,我唯一的猜测就是以某种方式我对网站服务器打电话太快,故意让我放慢速度。

**显然不是最好的书面代码,因为我是新手,并且受到一堆草率编码的影响。但它确实完美地执行了我想要的。问题是它在大约十分钟后变慢到爬行速度,这将无法正常工作。

以下是相关代码:

数组代码

import java.io.IOException;
import java.net.URL;

public class UrlArrayBuild {

private int page_count; //number of pages 
public URL[] urlArray;  //array of webpage url's

    public UrlArrayBuild(int page) { //object constructor
        page_count = page; //initializes page_count
        urlArray = new URL[page_count]; //initializes page_count
    }

    protected void buildArray() throws IOException { // method assigns strings to   UrlArray object
        int count; //counter for iteration
        for(int i = 0; i < page_count; i++) { //loops through 
            count = i * 60; //sets user number at end of page
            URL website = new URL("http://...." + count);
            urlArray[i] = website; //url address
            //System.out.println(urlArray[i]); //debug
        }
    }

    protected URL returnArrayValue(int index) {  //method returns string value in array of given index
        //System.out.println(urlArray[index]); //debug
        return urlArray[index];
    }

    protected int returnArrayLength() { //method returns length of array
        //System.out.println(urlArray.length); //debug
        return urlArray.length;

    }

}

读者代码

import java.net.*;
import java.io.*;

public class DataReader {

public static void main(String[] args) throws IOException {
    UrlArrayBuild PrimaryArray = new UrlArrayBuild(9642); //Creates array object
    PrimaryArray.buildArray();  //Builds array 

    //Create and initialize variables to use in loop
    URL website = null;  
    String inputLine = null;

            //Loops through array and reads source code
    for (int i = 0; i < PrimaryArray.returnArrayLength(); i++) {

        try {
            website = PrimaryArray.returnArrayValue(i);  //acquires url
            BufferedReader inputStream = new BufferedReader(new InputStreamReader(website.openStream()));  //reads url source code
            System.out.println(PrimaryArray.returnArrayValue(i));  //prints out website url.  I use it as a check to monitor progress
            while((inputLine = inputStream.readLine()) != null) {
                if (inputLine.isEmpty()) { //checks for blank lines
                    continue;
                } else {
                    //begin parsing code.  This is currently commented so there is nothing that occurs here
                }
            }
            inputStream.close();
        } finally {
             //extraneous code here currently commented out.  
        }
    }
}

4 个答案:

答案 0 :(得分:0)

某些延迟会导致网站出现问题,特别是如果它们内容丰富的话。这可能是一个原因。 解析也可能是一些延迟的因素。因此,我个人建议使用有用的库进行解析,这可能会更好地进行优化。 祝你好运!

答案 1 :(得分:0)

  1. 多线程应用程序,以便请求可以并发运行。或者,
  2. 重新架构以使用异步IO / HTTP请求。 Netty或MINA,或者可能只是原始的NIO。
  3. 这两个相关的解决方案都有很多工作,但遗憾的是,需要一个复杂的解决方案来解决您的问题。基本上,存在异步框架来解决这个问题。

答案 2 :(得分:0)

我认为在循环遍历数组时,您可以使用多线程技术和异步java方法调用来提高性能。

答案 3 :(得分:0)

您的代码没有明显的错误可以解释这一点。当然不在你向我们展示的代码中。您的代码不会保存正在读取的任何内容,因此无法以这种方式泄漏内存。它不应泄漏资源...因为如果有任何I / O异常,应用程序会立即终止。

(但是,如果您的代码在I / O异常后尝试继续,那么您需要将close()调用移动到finally块以避免套接字/文件描述符泄漏。)

很可能是服务器端或(可能)网络问题:

  • 查看650页标记附近的页面是否有异常。它们更大吗?它们是否需要额外的服务器端处理(意味着它们的交付速度会更慢)?

  • 查看服务器端负载(应用程序运行时)及其日志文件。

  • 检查是否已实施某种服务器请求限制;例如作为反DoS措施。

  • 检查是否已实施某种网络流量限制。

  • 还要检查客户端资源使用情况。我希望CPU使用率保持不变,或者在650页标记处尾随。如果CPU使用量增加,则会将怀疑重新带回应用程序。