NIO的实战教程(简单且高效)

1. 参考

建议按顺序阅读以下三篇文章
为什么NIO被称为同步非阻塞?
Java IO 与 NIO:高效的输入输出操作探究
【Java.NIO】Selector,及SelectionKey

2. 实战

我们将模拟一个简单的HTTP服务器,它将响应客户端请求并返回一个固定的响应("Hello, World!")。我们将使用IO和NIO两种不同的方式实现此服务器。
2.1 传统阻塞IO

java 复制代码
import java.io.*;
public class TraditionalIOExample {
    public static void main(String[] args) {
        try {
            // 打开文件
            InputStream input = new FileInputStream("example.txt");
            OutputStream output = new FileOutputStream("output.txt");

            // 读取和写入数据
            int data;
            while ((data = input.read()) != -1) {
                output.write(data);
            }

            // 关闭文件
            input.close();
            output.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.2 非阻塞NIO

java 复制代码
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

public class NioHttpServer {
    public static void main(String[] args) {
        try {
        	// 创建服务端通道
            ServerSocketChannel serverChannel = ServerSocketChannel.open();
            // 绑定访问端口
            serverChannel.socket().bind(new InetSocketAddress(8080));
            // 通道设置为非阻塞
            serverChannel.configureBlocking(false);

			// 通过open方法创建一个Selector
            Selector selector = Selector.open();
            /** 
            必须将channel注册到selector上,并订阅OP_ACCEPT事件
             		SelectionKey.OP_CONNECT  channel成功连接到另一个服务器称为"连接就绪"
					SelectionKey.OP_ACCEPT	 server socket channel准备好接收新进入的连接称为"接收就绪"
					SelectionKey.OP_READ	 有数据可读的通道可以说是"读就绪"
					SelectionKey.OP_WRITE	 有数据可写的通道可以说是"读就绪"
			*/
            serverChannel.register(selector, SelectionKey.OP_ACCEPT);

            while (true) {
            	// 返回你所感兴趣的事件(连接,接受,读或写)已经准备就绪的那些通道
                int readyChannels = selector.select();
                if (readyChannels == 0){
                	continue;
                }
                // 访问"已选择键集"中的就绪通道
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                
                // 可以遍历这个已选择的集合来访问就绪的通道
                Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
                while (keyIterator.hasNext()) {
                    SelectionKey key = keyIterator.next();
                    // 注意每次迭代末尾的remove()调用,Selector不会自己从已选择集中移除SelectioKey实例,必须在处理完通道时自己移除。
                    keyIterator.remove();

					// 一个server socket channel准备号接收新进入的连接称为"接收就绪"
                    if (key.isAcceptable()) {
                        ServerSocketChannel server = (ServerSocketChannel) key.channel();
                        // 客户端socker注册进来
                        SocketChannel clientChannel = server.accept();
                        clientChannel.configureBlocking(false);
                        clientChannel.register(selector, SelectionKey.OP_READ);
                        // 客户端通道是否有数据流进来
                    } else if (key.isReadable()) {
                        SocketChannel clientChannel = (SocketChannel) key.channel();
                        ByteBuffer buffer = ByteBuffer.allocate(1024);
                        clientChannel.read(buffer);
                        buffer.flip();
                        byte[] bytes = new byte[buffer.remaining()];
                        buffer.get(bytes);
                        String request = new String(bytes);

                        String response = "HTTP/1.1 200 OK\r\n\r\nHello, World!\r\n";
                        ByteBuffer responseBuffer = ByteBuffer.wrap(response.getBytes());
                        clientChannel.write(responseBuffer);
                        clientChannel.close();
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3. 模型

上述代码结合该模型,第二次阅读代码,会有更深的理解

4. 原理

多路复用才是NIO不阻塞的原因

相关推荐
不辉放弃42 分钟前
java连数据库
java·mysql
熊大如如8 小时前
Java 反射
java·开发语言
猿来入此小猿8 小时前
基于SSM实现的健身房系统功能实现十六
java·毕业设计·ssm·毕业源码·免费学习·猿来入此·健身平台
goTsHgo9 小时前
Spring Boot 自动装配原理详解
java·spring boot
卑微的Coder9 小时前
JMeter同步定时器 模拟多用户并发访问场景
java·jmeter·压力测试
pjx9879 小时前
微服务的“导航系统”:使用Spring Cloud Eureka实现服务注册与发现
java·spring cloud·微服务·eureka
多多*10 小时前
算法竞赛相关 Java 二分模版
java·开发语言·数据结构·数据库·sql·算法·oracle
爱喝酸奶的桃酥10 小时前
MYSQL数据库集群高可用和数据监控平台
java·数据库·mysql
唐僧洗头爱飘柔952711 小时前
【SSM-SSM整合】将Spring、SpringMVC、Mybatis三者进行整合;本文阐述了几个核心原理知识点,附带对应的源码以及描述解析
java·spring·mybatis·springmvc·动态代理·ioc容器·视图控制器
骑牛小道士11 小时前
Java基础 集合框架 Collection接口和抽象类AbstractCollection
java