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

            }
        }
    }
}
相关推荐
charlie1145141916 分钟前
嵌入式C++教程——ETL(Embedded Template Library)
开发语言·c++·笔记·学习·嵌入式·etl
陳10306 分钟前
C++:AVL树的模拟实现
开发语言·c++
小王不爱笑1327 分钟前
LangChain4J 整合多 AI 模型核心实现步骤
java·人工智能·spring boot
西凉的悲伤8 分钟前
spring-boot-starter-validation使用注解进行参数校验
java·spring boot·参数校验·validation·注解校验参数
LucDelton21 分钟前
Java 读取无限量文件读取的思路
java·运维·网络
zfoo-framework27 分钟前
docker desktop
开发语言
夹锌饼干30 分钟前
mysql死锁排查流程--(处理mysql阻塞问题)
java·mysql
小信丶40 分钟前
@EnableTransactionManagement注解介绍、应用场景和示例代码
java·spring boot·后端
m0_7369191042 分钟前
C++中的享元模式变体
开发语言·c++·算法
集芯微电科技有限公司1 小时前
15V/2A同步开关型降压单节/双节锂电池充电管理IC支持输入适配器 DPM 功能
c语言·开发语言·stm32·单片机·嵌入式硬件·电脑