概述
原则
最好在任何使用InputStream或者OutputStream的时候,及时关闭Stream。
典型示例
使用try with resource关闭流。
try (InputStream in = acquireStream()) {
// do something
...
}
或者finally删除。
InputStream in = null;
try {
in = acquireStream();
...
} finally {
if (in != null) in.close();
}
Stream流未关闭的问题
InputStream的作用是用来表示从不同数据源产生输入的类,这些数据源包括:
- 字节数组。
- String对象。
- 文件。
- 管道。
- 一个由其他种类的流组成的序列,以便我们可以将他们收集合并到一个流内。
- 网络数据源等。
InputStream数据源为文件
一个InputStream会占用一个极小的kernel资源,一个低级的file handle。
将文件读入InputStream,会打开一个新的InputStream,kernel会分配一个文件描述符,不停的读文件到InputStream,如果不close会导致打开的描述符累积,但是一个进程的文件描述符是有限的,所以每次使用完之后都加一个close()。
测试代码
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class TestInputStream {
public static void main(String[] args) {
testInputStreamWithOutClose();
}
/**
* 创建一万个测试文件
*/
public static void createTestFile() {
try {
for (int i = 0; i < 10000; i++) {
FileOutputStream fos = new FileOutputStream(new File(
"/Users/shenpengyan/Documents/workspace/Test/testInputStream/Test" + i));
fos.write(i);
fos.close();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 用不同文件,不使用close,有"Too many open files in system"报错
*/
public static void testInputStreamWithOutClose(){
try {
for (int i = 0; i < 10000; i++) {
FileInputStream fis = new FileInputStream(new File(
"/Users/shenpengyan/Documents/workspace/Test/testInputStream/Test" + i));
System.out.println(fis.toString() + " " + i);
// fis.close();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 用同一个文件,不加close,有"Too many open files in system"报错
*/
public static void testInputStreamWithOneFileWithOutClose(){
try {
for (int i = 0; i < 10000; i++) {
FileInputStream fis = new FileInputStream(new File(
"/Users/shenpengyan/Documents/workspace/Test/testInputStream/Test1"));
System.out.println(fis.toString() + " " + i);
// fis.close();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
当不使用close()方法时,会有报错:Too many open files in system
InputStream数据源是Internet
当我们把读到的图片存入InputStream来进一步处理时,如果不对InputStream进行close,经过测试,处理300个左右的请求后,就不能继续请求了。
这是因为InputStream没有被垃圾回收掉,还一直占用着连接,而图片服务商有连接数限制,导致之后的请求没有返回。