素材牛VIP会员
NIO 文件读写效率问题
 ju***23  分类:Java代码  人气:964  回帖:3  发布于6年前 收藏

我使用NIO完成一个大文件复制函数,但发现该函数的执行很不稳定。对此有以下困惑:

  1. 效率差异严重:每次复制文件耗时差异很大,且无规律,对一个2G的文件赋值,最快3秒,最慢达到20s;
  2. 内存泄露:JVM占用的内存并没有异常,但OS使用的内存迅速飙升,我猜测应该是“直接内存”的使用,但不清楚如何释放这部分内存;
  3. 系统负载:我观察到代码执行后,系统 CPU,内存,磁盘都迅速飙高,但代码停止后CPU,磁盘负载不能及时恢复;

环境信息:Windows10,JDK 8,具体代码如下:

public class CopyTest {

    private static final String PATH = "";  // TODO

    public static void main(String[] args) throws IOException {
        for (int i = 0; i < 10; i++) {
            fileChannelCopy();
        }
        System.in.read();
    }

    private static void fileChannelCopy() throws IOException {
        long start = System.currentTimeMillis();
        FileChannel read = new FileInputStream(PATH).getChannel();
        FileChannel writer = new RandomAccessFile(PATH + "-"
                + new Random(System.currentTimeMillis()).nextInt(), "rw").getChannel();
        long readSize = 0;
        long size = read.size() / 30;
        ByteBuffer toRead, toWrite = null;
        while (readSize < read.size() // 未读完
                && (read.size() - readSize) > size) {  // 剩余未读大于size
            toRead = read.map(FileChannel.MapMode.READ_ONLY, readSize, size);
            toWrite = writer.map(FileChannel.MapMode.READ_WRITE, readSize, size);
            toWrite.put(toRead);
            readSize += size;
            toRead.clear();
            toWrite.clear();
        }
        toRead = read.map(FileChannel.MapMode.READ_ONLY, readSize, read.size() - readSize);
        assert toWrite != null;
        toWrite.put(toRead);
        toRead.clear();
        toWrite.clear();
        read.close();
        writer.close();
        long end = System.currentTimeMillis();
        System.out.println("FileChannel copy file using " + (end - start) / 1000 + "s");
    }

某次执行Jprofiler观测到的运行状态

我发现复制的速度与CPU Load密切相关

 标签:ioniojava

讨论这个帖子(3)垃圾回帖将一律封号处理……

Lv5 码农
16***50 软件测试工程师 6年前#1

就我所了解的,磁盘是顺序读写设备,无论你有多少线程在读写,磁盘的数据读写是不能并发的。

Lv1 新人
10***19 学生 6年前#2

NIO用在网络上效果很好,但用在文件存取上似乎作用并不明显(除非下载文件这种场景,例如Tomcat的sendfile特性)。

用NIO和传统方法(FileInput/OutputStream)比较下就知道了。

Lv6 码匠
高***侠 UI设计师 6年前#3

操作系统文件缓存;java堆外内存;系统调用

 文明上网,理性发言!   😉 阿里云幸运券,戳我领取