• NIO学习



    前言

    NIO是JDK1.4版本带来的功能,区别于以往的BIO编程,同步非阻塞极大的节省资源开销,避免了线程切换和上下文切换带来的资源浪费。


    一、主要模块

    1. Selector:选择器,为事件驱动,做中央调度使用,一个选择器可以注册多个channel;
    2. Channel:通道,信息流通;支持读取和写入数据,一个通道可以有多个Buffer;
    3. Buffer:缓存区,存放数据,支持读取和写入的切换;

    二、使用步骤

    1.服务器端

    代码如下(示例):

    package nio;
     
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.Iterator;
    import java.util.Set;
     
    /**
     * Create by zjg on 2022/9/11
     */
    public class NIOServer {
        public static void main(String[] args) {
            try {
                ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
                serverSocketChannel.configureBlocking(false);
                serverSocketChannel.bind(new InetSocketAddress(6666));
                Selector selector =Selector.open();
                serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
                while(true){
                    if(selector.select(10000)==0){
                        System.out.println("没有接收到监听事件");
                        continue;
                    }
                    Set<SelectionKey> selectionKeys = selector.selectedKeys();
                    Iterator<SelectionKey> iterator = selectionKeys.iterator();
                    while (iterator.hasNext()){
                        SelectionKey selectionKey = iterator.next();
                        if(selectionKey.isAcceptable()){
                            System.out.println("获取到新的连接");
                            SocketChannel socketChannel = serverSocketChannel.accept();
                            socketChannel.configureBlocking(false);
                            socketChannel.register(selector,SelectionKey.OP_READ,ByteBuffer.allocate(1024));
                        }
                        if(selectionKey.isReadable()){
                            SocketChannel socketChannel = (SocketChannel)selectionKey.channel();
                            ByteBuffer byteBuffer = (ByteBuffer) selectionKey.attachment();
                            int read = socketChannel.read(byteBuffer);
                            if(read==-1){
                                selectionKey.cancel();
                            }else{
                                String req=new String(byteBuffer.array()).trim();
                                System.out.println("nio客户端说:"+req);
                                String res= "服务器响应["+LocalDateTime.now().format(DateTimeFormatter.ISO_DATE)+" "+LocalDateTime.now().format(DateTimeFormatter.ISO_TIME)+"]:"+req;
                                System.out.println(res);
                                socketChannel.write(ByteBuffer.wrap(res.getBytes()));
                            }
                        }
                        iterator.remove();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    在这里插入图片描述

    2.客户端

    代码如下(示例):

    package nio;
     
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.SocketChannel;
     
    /**
     * Create by zjg on 2022/9/11
     */
    public class NIOClient {
        public static void main(String[] args) {
            try {
                SocketChannel socketChannel = SocketChannel.open();
                socketChannel.configureBlocking(false);
                InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 6666);
                if(!socketChannel.connect(inetSocketAddress)){
                    while (!socketChannel.finishConnect()){
                        System.out.println("等待连接完成!");
                    }
                }
                String message="向往自由!";
                ByteBuffer byteBuffer = ByteBuffer.wrap(message.getBytes());
                socketChannel.write(byteBuffer);
                System.out.println("请求完成!");
                ByteBuffer allocate = ByteBuffer.allocate(1024);
                while (true){
                    int read = socketChannel.read(allocate);
                    if(read==0){
                        continue;
                    }
                    System.out.println("---"+new String(allocate.array()).trim());
                    socketChannel.close();
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    在这里插入图片描述

    三、NIO零拷贝(推荐)

    package nio;
     
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.nio.channels.FileChannel;
     
    /**
     * Create by zjg on 2022/9/11
     */
    public class NIOZeroCopy {
        public static void main(String[] args) {
            FileChannel src = null;
            FileChannel dest = null;
            try {
                src=new FileInputStream("2.txt").getChannel();
                dest=new FileOutputStream("3.txt").getChannel();
                long start = System.currentTimeMillis();
                src.transferTo(0,src.size(),dest);
                long end = System.currentTimeMillis();
                System.out.println("copy完成,共"+src.size()+"byte,用时"+(end-start)+"毫秒");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if(src!=null){
                    try {
                        src.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(dest!=null){
                    try {
                        dest.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    在这里插入图片描述

    四、NIO另一种copy

    package nio;
     
    import java.io.File;
    import java.io.IOException;
    import java.nio.file.Files;
     
    /**
     * Create by zjg on 2022/9/18
     */
    public class NIOTest {
        public static void main(String[] args) {
            File source=new File("2.txt");
            File target=new File("4.txt");
            try {
                long start = System.currentTimeMillis();
                Files.copy(source.toPath(),target.toPath());
                long end = System.currentTimeMillis();
                System.out.println("copy完成,共"+source.length()+"byte,用时"+(end-start)+"毫秒");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述
    效率稍微慢点,用起来简单。


    总结

    回到顶部
    刚开始写,请大佬指点。

  • 相关阅读:
    RealEvo许可证协议
    程序员告别996,这款开发工具火了
    C#基础--对象和类型
    学习 OpenStack 的新指南和教程的六个建议
    做自媒体影视短视频剪辑号,在哪儿下载素材?
    有哪些开源通用流程引擎
    Python3高级特性(五)之容器(container)
    GSAman | 我「玩着游戏」就把「科研做了」
    YOLOv7 PyQt5 | 手把手教你YOLOv7添加PyQt页面
    机器学习西瓜书——第五章 神经网络
  • 原文地址:https://blog.csdn.net/qq_44824164/article/details/137840037