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();
        }
    }
}

在这里插入图片描述

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();
        }
    }
}

在这里插入图片描述

三、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();
                }
            }
        }
    }
}

在这里插入图片描述

四、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. <span style='color:red;'>NIO</span><span style='color:red;'>学习</span>

    NIO学习

    2024-04-20 22:02:06      45 阅读
  2. NIO学习笔记

    2024-04-20 22:02:06       19 阅读
  3. 算法学习笔记(Nim游戏)

    2024-04-20 22:02:06       12 阅读
  4. 学习回顾No.6

    2024-04-20 22:02:06       29 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-20 22:02:06       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-20 22:02:06       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-20 22:02:06       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-20 22:02:06       20 阅读

热门阅读

  1. c++入门

    c++入门

    2024-04-20 22:02:06      13 阅读
  2. SQL序列

    2024-04-20 22:02:06       27 阅读
  3. 美式英语和英式英语的不同之处

    2024-04-20 22:02:06       14 阅读
  4. SQL优化——成本计算

    2024-04-20 22:02:06       15 阅读
  5. NLP预训练模型- GPT-3学习指南与学习总结案例

    2024-04-20 22:02:06       15 阅读
  6. 谈谈Python在机器学习和人工智能领域的应用

    2024-04-20 22:02:06       13 阅读