我写了一个程序,它连接到网站并获取网页的标题。我从一个可以插入程序中的文本中获取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()
。两者都对内存使用没有影响。
答案 0 :(得分:2)
如果我有10个线程和10个URL,我的程序使用大约100 MB的内存。
一般性评论。
在任何时间点存在10个(或100个)BufferedReader
个对象当然没有问题。默认缓冲区大小为8k字符或16k字节。其中100个将是几个megs。每个帖子应该一次从一个BufferedReader
读取,您应该close()
并设置为null
(见下文)in
块中的try {} finally {}
确保正确释放内存,即使是IOException
。
如果内存泄漏确实在BufferedReader
,那么你显然是以某种方式保留对它们的引用。在它上面调用close()
是不够的,因为它不会释放底层缓冲区。您应该将in
字段和引用它们的其他位置设置为null
,以确保GC可以获得它。也许持有BufferedReader
的班级会被收藏在一个集合中?
要考虑的一件事是限制队列中未完成的URL数量。了解URL队列的大小可能会告诉您队列中保留的内存量。您可能会考虑使用String
而不是URL
或更重的队列。限制队列的大小将无法正常工作,因为它会阻止您的线程处理页面,甚至可能导致死锁。
答案 1 :(得分: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快,
答案 2 :(得分:-1)
我不确定它会有所帮助,但你也应该关闭InputStreamReader。