1

我编写了一个连接到网站并获取网页标题的程序。我从可以插入程序中的文本中获取 URL,然后所有 url 都在一个列表中。为了加快速度,我使用了多个线程。例如,如果我有 10 个线程和 10 个 URL,我的程序将使用大约 100 MB 内存。但是,如果我有 5 个线程和 10 个 URL,那么每个线程必须连接到两个网站,我的内存使用量会上升到大约 1.3 GB。我发现这是代码中的一行让我的程序使用了这么多内存:

in = new BufferedReader(new InputStreamReader(spoof.getInputStream()));

在这个方法中:

private BufferedReader in;
private URL url;
private URLConnection spoof;

private void openConnection() {

    try {
        url = new URL(tag.url);
        spoof = url.openConnection();
        spoof.setRequestProperty("User-Agent", userAgent);

        in = new BufferedReader(new InputStreamReader(spoof.getInputStream()));

    } catch (IOException ex) {
        tag.ableToConnect = false;
    }
}

我试图关闭 BufferedReader 并运行手册System.gc()。两者都对内存使用没有影响。

如果你能帮助我,我会很高兴。谢谢!

4

3 回答 3

2

例如,如果我有 10 个线程和 10 个 URL,我的程序将使用大约 100 MB 内存。

几个一般性评论。

  1. BufferedReader在任何时间点都存在 10 个(或 100 个)对象当然没有问题。默认缓冲区大小为 8k 字符或 16k 字节。其中100个将是几兆。每个线程应该一次从一个线程读取,BufferedReader并且您应该close()并设置为null(见下文)in在一个try {} finally {}块中,以确保您正确释放内存,即使在IOException.

  2. 如果确实存在内存泄漏,BufferedReader那么您显然是以某种方式保留对它们的引用。调用close()它是不够的,因为它不会释放底层缓冲区。您应该设置in引用它们的字段和其他位置,null以确保 GC 可以获取它。也许坚持的类BufferedReader被保存在一个集合或其他东西中?

  3. 要考虑的一件事是限制队列中未完成的 URL 的数量。知道 URL 队列有多大可能会告诉您队列本身中保留的内存量。您可能会考虑只使用队列String而不是URL或任何更重的东西。限制队列的大小不会完美工作,因为它会阻止你的线程处理页面,甚至可能导致死锁。

于 2013-11-03T15:39:57.787 回答
0

1)尝试inputstreamreader 2)不要尝试读取所有按行读取的块

public class BufferedReaderExample {   

    public static void main(String args[]) {

        //reading file line by line in Java using BufferedReader       
        FileInputStream fis = null;
        BufferedReader reader = null;

        try {
            fis = new FileInputStream("C:/sample.txt");
            reader = new BufferedReader(new InputStreamReader(fis));

            System.out.println("Reading File line by line using BufferedReader");

            String line = reader.readLine();
            while(line != null){
                System.out.println(line);
                line = reader.readLine();
            }           

        } catch (FileNotFoundException ex) {
            Logger.getLogger(BufferedReaderExample.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(BufferedReaderExample.class.getName()).log(Level.SEVERE, null, ex);

        } finally {
            try {
                reader.close();
                fis.close();
            } catch (IOException ex) {
                Logger.getLogger(BufferedReaderExample.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
  } 

阅读更多: http: //javarevisited.blogspot.com/2012/07/read-file-line-by-line-java-example-scanner.html#ixzz2jVVs2RMN 如果速度是个问题,你可以看看在 [java.nio][1] 包中 - 这些包据说比 java.io 快,

于 2013-11-02T16:42:55.517 回答
-1

我不确定它是否会有所帮助,但您还应该关闭 InputStreamReader。

于 2013-11-02T16:42:15.303 回答