Java 基础之NIO 学习详解

Java 基础之NIO 学习详解

简述

NIO,全称为“New IO”,是Java 1.4 引入的一套用于更高效的 I/O 操作的API。NIO主要包括以下三个核心组件:Channel、Buffer 和 Selector。其中,Channel 和 Buffer 主要用于底层数据传输,Selector 则用于监听 Channel 上的 IO 事件。

NIO 与传统 IO 的区别

在传统 IO 模型中,当一个线程被分配到一个 Socket 后,这个线程就会一直阻塞等待,直到数据到达,而在 NIO 模型中,数据异步地读取到缓冲区,线程可以继续处理其他请求,从而提高了系统的并发处理能力。

NIO 的核心组件

Channel

Channel 可以看作是一个数据源的抽象。例如文件、网络套接字或一个能够实现 I/O 操作的硬件设备都可以通过 Channel 进行数据读写。Channel 与 Stream 的区别就像是将数据源分成了读取与写入两个部分。

Buffer

Buffer 可以看作是一个存储字节的数组。它有一个指针 position 表示下一个读或写的位置,一个 limit 表示结束位置,一个 capacity 表示数组的容量。当Buffer缓冲区中有数据读写时,指针 position 会向前移动。

Selector

Selector 用于监听多个 Channel 上的 I/O 事件。因为在 NIO 中,一个线程可以监听多个 Channel,因此使用 Selector 可以节省线程开销,提高程序的并发性能。

NIO应用

下面我们来看一些 NIO 应用实例。

示例1:NIO读取文件

public static void readFile(String path) throws IOException {
    RandomAccessFile file = new RandomAccessFile(path, "rw");
    FileChannel channel = file.getChannel();

    // 初始化 ByteBuffer
    ByteBuffer buffer = ByteBuffer.allocate(1024);

    int bytesRead = channel.read(buffer);
    while (bytesRead != -1) {
        // 将 ByteBuffer 从写模式变成读模式
        buffer.flip();

        while (buffer.hasRemaining()) {
            System.out.print((char) buffer.get());
        }

        buffer.clear();
        bytesRead = channel.read(buffer);
    }

    channel.close();
    file.close();
}

示例2:NIO服务器

这是一个基于NIO的简单服务器应用,可以同时处理多个客户端请求。

public static void server() throws IOException {
    // 创建 ServerSocketChannel
    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    serverSocketChannel.socket().bind(new InetSocketAddress(8888));
    serverSocketChannel.configureBlocking(false);

    // 创建 Selector
    Selector selector = Selector.open();
    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

    while (true) {
        int readyChannelsCount = selector.select();
        if (readyChannelsCount == 0) {
            continue;
        }

        Set<SelectionKey> selectedKeys = selector.selectedKeys();
        Iterator<SelectionKey> iterator = selectedKeys.iterator();
        while (iterator.hasNext()) {
            SelectionKey key = iterator.next();
            if (key.isAcceptable()) {
                // 新的客户端连接
                SocketChannel socketChannel = ((ServerSocketChannel) key.channel()).accept();
                socketChannel.configureBlocking(false);
                socketChannel.register(selector, SelectionKey.OP_READ);
                System.out.println("New client connected");
            } else if (key.isReadable()) {
                // 读取客户端请求
                SocketChannel socketChannel = (SocketChannel) key.channel();
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                int bytesRead = socketChannel.read(buffer);
                if (bytesRead > 0) {
                    buffer.flip();
                    String request = new String(buffer.array(), 0, bytesRead);
                    System.out.println("Received request: " + request);

                    // 处理请求

                    // 发送响应
                    buffer.clear();
                    String response = "Hello, client";
                    buffer.put(response.getBytes());
                    buffer.flip();
                    socketChannel.write(buffer);
                } else {
                    socketChannel.close();
                    System.out.println("Client disconnected");
                }
            }
            iterator.remove();
        }
    }
}

以上是关于 NIO 的一个简单介绍以及两个示例的详细说明。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java 基础之NIO 学习详解 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • 详解Spring Kafka中关于Kafka的配置参数

    下面我来详细讲解一下关于“详解Spring Kafka中关于Kafka的配置参数”的完整攻略。 1. Kafka中常用的配置参数 在使用Kafka时,可以通过配置不同的参数来更加灵活地自定义Kafka的行为。下面是Kafka中一些常用的配置参数: bootstrap.servers:Kafka集群的连接地址列表,指定了Kafka Broker的主机名和端口号…

    Java 2023年5月20日
    00
  • Tomcat环境变量如何配置

    Tomcat是一个用于Java应用程序的Web服务器和Servlet容器。在使用Tomcat的过程中,为了保证Web应用程序的正常运行,需要正确地配置Tomcat环境变量。下面是配置Tomcat环境变量的完整攻略: 1. 下载和安装Tomcat 在开始配置Tomcat环境变量之前,我们首先需要下载和安装Tomcat。Tomcat的下载地址为:https://…

    Java 2023年5月19日
    00
  • Java中对AtomicInteger和int值在多线程下递增操作的测试

    测试Java中对AtomicInteger和int值在多线程下递增操作的方法可以分为以下几步: 步骤一:编写测试代码 首先,需要编写一个测试类来测试多线程下AtomicInteger和int值的递增操作。下面是一个简单的示例代码,其中定义了一个递增的Counter类,包含了两个方法increase()和getValue()。在increase()方法中,使用…

    Java 2023年5月19日
    00
  • 微信小程序实现无缝滚动

    准备工作 微信小程序的开发环境 基本的HTML、CSS、JavaScript知识 微信小程序开发文档 实现步骤步骤一:建立一个scroll组件 在wxml文件中使用scroll组件 <scroll-view scroll-x="{{scrollX}}" scroll-y="{{scrollY}}" style=&…

    Java 2023年5月23日
    00
  • Servlet关于RequestDispatcher的原理详解

    《Servlet关于RequestDispatcher的原理详解》 什么是RequestDispatcher? RequestDispatcher是Servlet规范中的一种技术,用于在一个Web应用程序内部将请求转发到另一个Servlet或JSP页面,是一种实现Servlet之间跳转和调用的方法。 RequestDispatcher的工作原理 Reques…

    Java 2023年6月15日
    00
  • Java实现中国象棋的示例代码

    下面是“Java实现中国象棋的示例代码”的完整攻略: 1. 确定需求和分析 在实现中国象棋的过程中,需要先明确需求和进行分析。具体来说,我们需要了解中国象棋的规则、棋盘、棋子等基本信息,然后根据需求进行代码的设计和实现。 2. 代码设计 首先,我们需要了解如何存储和表示棋盘和棋子的信息。一般而言,可以使用二维数组来表示棋盘,然后用整数或字符来表示棋子的种类。…

    Java 2023年5月19日
    00
  • JSP页面传值乱码过滤方法

    当我们使用JSP页面传输数据时,经常会遇到传输中文字符出现乱码的问题。这时候,我们就需要对传输数据进行过滤,以解决乱码问题。本文将详细讲解如何使用JSP页面传值乱码过滤方法。 什么是JSP页面传值乱码过滤方法 JSP页面传值乱码过滤方法,是一种对JSP传输数据进行编码、解码的方法。通过该方法,我们可以在数据传输的过程中进行字节编码,以避免造成字符编码的乱码现…

    Java 2023年6月15日
    00
  • java static块和构造函数的实例详解

    Java中的static块和构造函数都是用来初始化类的成员变量的,但两者有着不同的特点和应用场景。下面详细讲解static块和构造函数的用法及其区别。 一、static块 1.1 定义 在Java中,static块是一个静态代码块,用来初始化静态成员变量。在类加载时,如果类中有static块,则首先会执行static块,然后才会执行其他代码块和构造函数。 1…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部