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):改方法用于接收客户端的数据,直到有数据才会返回,否则将一直阻塞线程。

java 复制代码
    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 设置为非阻塞模式。

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

java 复制代码
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();
                }

            }
        }
    }
}
相关推荐
28岁青春痘老男孩9 小时前
JDK8+SpringBoot2.x 升级 JDK 17 + Spring Boot 3.x
java·spring boot
方璧9 小时前
限流的算法
java·开发语言
元Y亨H9 小时前
Nacos - 服务注册
java·微服务
Hi_kenyon9 小时前
VUE3套用组件库快速开发(以Element Plus为例)二
开发语言·前端·javascript·vue.js
曲莫终9 小时前
Java VarHandle全面详解:从入门到精通
java·开发语言
一心赚狗粮的宇叔9 小时前
中级软件开发工程师2025年度总结
java·大数据·oracle·c#
奋进的芋圆10 小时前
DataSyncManager 详解与 Spring Boot 迁移指南
java·spring boot·后端
ghie909010 小时前
基于MATLAB GUI的伏安法测电阻实现方案
开发语言·matlab·电阻
Gao_xu_sheng10 小时前
Inno Setup(专业安装/更新 EXE)
开发语言