当前位置: 首页 > article >正文

NIO入门

IO和NIO的区别:

  1. IO:通过流处理数据,仅支持阻塞IO。
    核心组件:InputStream /OutputStream用于字节的读写,Reader / Writer:用于字符流的读写。读取过程中无法被中断,是阻塞式IO。
  2. NIO:通过管道处理数据,支持阻塞IO和非阻塞IO。
    核心组件:Channel通道、Buffer缓冲区、Selector选择器。Channel与Buffer做直接交互,用于数据的传输,支持非阻塞IO,Buffer用于存放数据,Selector用于管理多个管道,允许单个线程处理多个IO。


Channel与Buffer联调

阻塞IO案例

ServerSocketChannel.accept():该方法用于等待客户端连接,直到有客户端连接才会返回,如果没有客户端连接则会一直阻塞。

SocketChannel.read(ByteBuffer):改方法用于接收客户端的数据,直到有数据才会返回,否则将一直阻塞线程。

    package com.jiawa.netty.server;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.util.List;
    
    import static com.jiawa.netty.utils.ByteBufferUtil.debugAll;
    
    public class Server {
        private static final Logger logger = LoggerFactory.getLogger(Server.class);
    
        public static void main(String[] args) throws IOException {
            //创建缓存、缓存客户端信息
            ByteBuffer buffer = ByteBuffer.allocate(16);
    
            //创建服务器
            ServerSocketChannel server = ServerSocketChannel.open();
    
    
            //绑定端口
            server.bind(new InetSocketAddress(8080));
    
            //创建客户端存储集合
            List<SocketChannel> clients = new java.util.ArrayList<>();
    
            //接收客户端
            while (true) {
                //阻塞线程,直到有客户端请求连接后释放
                SocketChannel client = server.accept();
    
                //如果有客户端请求,则返回客户端信息
                logger.info("收到客户端请求:{}", client);
                clients.add(client);
    
                for (SocketChannel c : clients) {
                    //读取客户端数据
                    int read = c.read(buffer);
                    if (read > 0) {
                        logger.info("读取客户端数据:{}", read);
                        //打开读
                        buffer.flip();
                        //打印数据
                        debugAll(buffer);
                        //清空
                        buffer.clear();
                    }
    
                }
            }
        }
    }

非阻塞IO案例

server.configureBlocking(false):将 ServerSocketChannel 设置为非阻塞模式。

client.configureBlocking(false):将每个 SocketChannel 设置为非阻塞模式。

设置为非阻塞之后,则不会阻塞线程,不管是否有客户端连接或者接收客户端数据,都会直接返回,不会阻塞线程。

package com.jiawa.netty.server;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.List;

import static com.jiawa.netty.utils.ByteBufferUtil.debugAll;

public class Server {
    private static final Logger logger = LoggerFactory.getLogger(Server.class);

    public static void main(String[] args) throws IOException {
        //创建缓存、缓存客户端信息
        ByteBuffer buffer = ByteBuffer.allocate(16);

        //创建服务器
        ServerSocketChannel server = ServerSocketChannel.open();

        //非阻塞
        if (server!= null){
            server.configureBlocking(false);
        }

        //绑定端口
        server.bind(new InetSocketAddress(8080));

        //创建客户端存储集合
        List<SocketChannel> clients = new java.util.ArrayList<>();

        //接收客户端
        while (true) {
            //阻塞线程,直到有客户端请求连接后释放
            SocketChannel client = server.accept();

            //将客户端设置为非阻塞
            if (client != null) {
                client.configureBlocking(false);
            }

            //如果有客户端请求,则返回客户端信息
            if (client != null) {
                logger.info("收到客户端请求:{}", client);
                clients.add(client);
            }


            for (SocketChannel c : clients) {
                //读取客户端数据
                int read = c.read(buffer);
                if (read > 0){
                    logger.info("读取客户端数据:{}", read);
                    //打开读
                    buffer.flip();
                    //打印数据
                    debugAll(buffer);
                    //清空
                    buffer.clear();
                }

            }
        }
    }
}


http://www.kler.cn/a/595101.html

相关文章:

  • VSCode中搜索插件显示“提取扩展时出错。Failed to fetch”问题解决!
  • 平安信托张中朝:养老信托将助力破解“中国式养老”难题
  • 数智读书笔记系列021《大数据医疗》:探索医疗行业的智能变革
  • CUDA编程面试高频30题
  • MyBatis注解方式:从CRUD到数据映射的全面解析
  • eBPF调研-附上参考资源
  • FPGA 以太网通信(三)
  • openvela新时代的国产开源RTOS系统
  • SQL Server数据库表删除分区
  • Redis 实现分布式锁全解析:从原理到实践
  • Flink CDC 与 SeaTunnel CDC 简单对比
  • 【踩坑日记】IDEA的ctrl+r快捷键冲突无法使用
  • ISSN号是什么?连续出版物标识的应用与生成
  • 第六篇:Setup:组件渲染前的初始化过程是怎样的?
  • 明远智睿SD2351核心板:多接口融合,破解边缘计算难题
  • 从零开始学Seata:分布式事务的终极解决方案
  • 蓝桥杯每日一题----一维差分
  • await func().catch()和try{ func() }.catch(),两种写法,有什么区别
  • 第2.2节 Android Jacoco插件覆盖率采集
  • Claude 3.7 Sonnet 根据UI设计稿生成前端html页面