Java IO 模型(4)

Java IO 模型

3.8 NIO 与 零拷贝

零拷贝从操作系统角 度,是没有cpu拷贝

3.8.1 基本介绍

在这里插入图片描述

正常IO:file -> page cache -> application cache -> socket cache -> nic
零拷贝:file - > page cache -> nic

零拷贝优势:
○ 减少的数据复制,减轻内存与CPU压力
○ 减少用户态与内核态之间的来回切换

java 中常用的零拷贝 mmap(内存映射)和 sendFile

3.8.2 传统IO

在这里插入图片描述

public class NIOZeroCopyOldServer {

    public static void main(String[] args) throws Exception {

        ServerSocket serverSocket = new ServerSocket(8090);

        while (true) {

            Socket socket = serverSocket.accept();
            InputStream inputStream = socket.getInputStream();

            byte[] buffer = new byte[8 * 1024];

            while ((inputStream.read(buffer, 0, buffer.length)) != -1) {

            }
        }
    }
}
public class NIOZeroCopyOldClient {

    public static void main(String[] args) {

        Socket socket = null;
        FileInputStream inputStream = null;
        DataOutputStream outputStream = null;

        try {

            socket = new Socket("127.0.0.1", 8090);
            outputStream = new DataOutputStream(socket.getOutputStream());

            inputStream = new FileInputStream(new File("files//Typora.zip"));

            byte[] buffer = new byte[8 * 1024];

            long read;
            long total = 0; //统计文件字节数

            long startTime = System.currentTimeMillis();

            while ((read = inputStream.read(buffer)) != -1) {

                total += read;
                outputStream.write(buffer);

            }

            System.out.println("发送总字节数: " + total + ", 耗时: " + (System.currentTimeMillis() - startTime));

        } catch (IOException e) {
            e.printStackTrace();
        } finally {

            try {
                outputStream.close();
                inputStream.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3.8.3 mmap(Memory map)

在这里插入图片描述

mmap通过内存映射,将文件映射到内核缓冲区,同时,用户空间可以共享内核 空间的数据。这样,在进行网络传输时,就可以减少内核空间到用户控件的拷贝次数

public class NIOZeroCopyServer {

    public static void main(String[] args) throws Exception{

        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        serverSocketChannel.socket().bind(new InetSocketAddress("127.0.0.1",8090));

        ByteBuffer buffer = ByteBuffer.allocate(8 * 1024);

        while (true){

            SocketChannel socketChannel = serverSocketChannel.accept();

            int read = 0;

            while ((read = socketChannel.read(buffer)) != -1){

                buffer.rewind();

            }
        }
    }
}

public class NIOZeroCopyClient {

    public static void main(String[] args) throws Exception {

        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.connect(new InetSocketAddress("127.0.0.1", 8090));

        File file = new File("files//Typora.zip");

        long fileSize = file.length();

        System.out.println("文件大小 fileSize = " + fileSize);

        FileInputStream inputStream = new FileInputStream(file);
        FileChannel inputStreamChannel = inputStream.getChannel();

        //在linux下一个transferTo 方法就可以完成传输
        //在windows 下 一次调用 transferTo 只能发送 8m , 就需要分段传输文件, 而且要主要
        //传输时的位置 =》 课后思考...
        //transferTo 底层使用到零拷贝

        long count = (long) ((fileSize % (8 * 1024 * 1024)) == 0 ? fileSize / (8 * 1024 * 1024) : fileSize / (8 * 1024 * 1024) + 1);

        int position = 0;

        long startTime = System.currentTimeMillis();

        while (count-- > 0) {

            long transferCount = inputStreamChannel.transferTo(position, 8 * 1024 * 1024, socketChannel);

            System.out.println("发送的总的字节数 =" + transferCount + " 耗时:" + (System.currentTimeMillis() - startTime));

            position += (8 * 1024 * 1024);
        }

        //关闭
        inputStreamChannel.close();

    }

}

3.8.4 snedFile

Linux 2.1 sendFile
在这里插入图片描述
Linux 2.1版本提供了 sendFile函数,其基本 原理如下:数据根本不 经过用户态,直接从内 核缓冲区进入到Socket Buffer,同时,由于和用 户态完全无关,就减少 了一次上下文切换

Linux 2.4 sendFile

在这里插入图片描述
Linux在2.4版本中,做了 一些修改,避免了从内核 缓冲区拷贝到Socket buffer的操作,直接拷贝到 协议栈,从而再一次减少 了数据拷贝

3.9 原生 NIO 时序图

server

在这里插入图片描述

client

在这里插入图片描述

4 AIO (NIO2.0)

4.1 介绍

http://www.52im.net/thread-306-1-1.html

4.2 BIO、NIO、AIO对比

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值