zoukankan      html  css  js  c++  java
  • Java:浅谈InputStream的close方法

    原则:最好在任何时候使用InputStream或者OutputStream的时候,在finally中调用close()方法,显式关闭。

    一个典型的示例

    InputStream in = null;
    try {
        in = acquireStream();
        ...
    } finally {
        if (in != null) in.close();
    }
    

    fianlly中的if (in != null) in.close();也可以用IOUtils.closeQuietly(in);代替,需要Apache Commons-IO

    为什么需要调用

    InputStream的作用是用来表示从不同数据源产生输入的类,这些数据源包括:

    • 字节数组
    • String对象
    • 文件
    • 管道
    • 一个由其他种类的流组成的序列,以便我们可以将他们收集合并到一个流内。
    • 其他数据源,如Internet连接等

    通常不使用close会导致内存泄露,垃圾回收机制会回收,但是最好自己显式关闭,这并不是特别关键。

    关键是当InputStream的数据源是文件或者Internet连接的时候。

    OutputStream的作用是如FileOutStream,当不调用close的时候,不会将缓存刷入文件中。

    InputStream的数据源是文件时

    一个InputStream会韩勇一个极小的kernel资源,一个低级的file handle。
    当打开文件时,将文件读入到InputStream,会对文件加锁。当你不考虑文件加锁。当你需要读取另一个文件的时候,会打开一个新的InputStream,kernel会分配另一个descriptor(文件流),一直累加,而一个进程的文件描述表是优先,到最后文件描述表将用被用完,所以为了以防万一,最好每次使用完之后都加一个close()

    测试代码

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    
    public class TestInputStream {
        public static void main(String[] args) {
    //        createTestFile();
    //        testInputStreamWithOutClose();
    //        testInputStreamWithOneFileWithOutClose();
            testInputStreamWithClose();
        }
    
        /**
         * 创建一万个测试文件
         */
        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"报错
         */
        public static void testInputStreamWithClose(){
            try {
                for (int i = 0; i < 100000; 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

    java.io.FileInputStream@7e349a0e 6079
    java.io.FileNotFoundException: /Users/shenpengyan/Documents/workspace/Test/testInputStream/Test1 (Too many open files in system)
    	at java.io.FileInputStream.open(Native Method)
    	at java.io.FileInputStream.<init>(FileInputStream.java:120)
    	at TestInputStream.testInputStreamWithOneFileWithOutClose(TestInputStream.java:53)
    	at TestInputStream.main(TestInputStream.java:9)
    
    
    InputStream的数据源是Internet连接时

    这是我实际遇到的情况,实际业务情况为:我需要调用一个图片存储位置,用key读到的图片存到InputStream里面来进行进一步处理,而我忘记了对它进行close,经过测试,处理300左右的请求之后,就不能继续请求了,这是为什么呢?是因为InputStream没有被垃圾回收掉,还一直占用着连接,而图片服务商有连接数限制,导致之后的请求没有返回,被调用的InputStream类如下:

    import java.io.FilterInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.SocketException;
    
    import org.apache.http.client.methods.CloseableHttpResponse;
    
    public class ObjectInputStream extends FilterInputStream {
    
        private CloseableHttpResponse httpResponse;
    
        public ObjectInputStream(InputStream in, CloseableHttpResponse httpResponse) {
            super(in);
            this.httpResponse = httpResponse;
        }
    
        public void close() throws IOException {
            this.httpResponse.close();
            try {
                super.close();
            } catch (SocketException e) {
                // expected from some implementations because the stream is closed
            }
        }
    }
    

    当没有调用close方法的时候,没有调用httpResponse.close();,连接不会关掉,所以就尴尬了。

    理论依据参考:http://stackoverflow.com/questions/26541513/why-is-it-good-to-close-an-inputstream

  • 相关阅读:
    bzoj4010 [HNOI2015]菜肴制作
    PHP--------TP中的ajax请求
    二维数组去重
    手机号138-0013-8000格式存储
    spring4-2-bean配置-1-依赖注入
    spring4-1-Spring的简单介绍
    Result Grouping / Field Collapsing-结果分组
    vim自动补全
    vim配置-程序员【转】
    服务端程序设计和实现总结 【转】
  • 原文地址:https://www.cnblogs.com/shenpengyan/p/6117814.html
Copyright © 2011-2022 走看看