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日

相关文章

  • springboot项目配置多个kafka的示例代码

    下面是关于springboot项目配置多个kafka的攻略。 配置pom.xml文件 首先,在pom.xml文件中添加kafka和spring-kafka的依赖: <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spri…

    Java 2023年5月20日
    00
  • Android打包篇:Android Studio将代码打包成jar包教程

    我将为你详细讲解“Android打包篇:Android Studio将代码打包成jar包教程”的完整攻略。 一、前置条件 在进行此教程之前,需要保证以下条件已经满足: 你已经安装了Android Studio; 你已经构建了一个Android项目,并且需要将其中的某些代码打包成Jar包; 你已经了解过Java打包,熟悉Java打包命令。 二、步骤 接下来我们…

    Java 2023年5月26日
    00
  • 用定制标签库和配置文件实现对JSP页面元素的访问控制

    实现对JSP页面元素的访问控制,可以通过定义自定义标签来实现。通过在JSP页面引入自定义标签库,并根据标签的属性值控制对应元素的显示与隐藏,从而实现访问控制的目的。 以下是实现步骤: 在项目中创建自定义标签库文件(例如custom.tld),定义自定义标签及其属性。例如: <taglib xmlns="http://java.sun.com/…

    Java 2023年6月15日
    00
  • java判断中文字符串长度的简单实例

    下面是详细讲解“Java判断中文字符串长度的简单实例”的完整攻略: 1. 背景介绍 在Java开发中,经常会遇到需要对中文字符串长度进行判断的需求。但是,由于中文字符所占的字节数不同于英文字符,所以在计算中文字符串长度时需要进行特殊处理。 2. 判断中文字符串长度的方法 在Java中,可以使用以下两种方法判断中文字符串长度: 2.1. 使用String类的l…

    Java 2023年5月27日
    00
  • Java连接MySQL数据库实例

    下面我将为大家详细讲解Java连接MySQL数据库实例的完整攻略。主要分为以下步骤: 步骤一:下载安装MySQL 首先需要下载并安装MySQL数据库,可以通过官网下载及安装。安装完成后,需要在MySQL中创建一个数据库及数据表。具体操作如下:1. 进入MySQL命令行客户端2. 创建一个数据库:CREATE DATABASE database_name;3.…

    Java 2023年5月19日
    00
  • 详解Jvm中时区设置方式

    我来详细讲解一下“详解Jvm中时区设置方式”的完整攻略。 什么是Jvm中的时区 Jvm是一种Java虚拟机,它是运行Java程序的基础。在Java程序中,时间是一个非常重要的概念,因此时区是一个必不可少的因素。Jvm中的时区设置可以控制Java程序使用的时间和日期格式。 Jvm中的时区设置方式 Jvm中的时区设置有三种方式,分别为: 1. 系统默认时区 Jv…

    Java 2023年5月20日
    00
  • Java获取时间年、月、日的方法

    下面是详细讲解 Java 获取时间年、月、日的方法的攻略。 获取当前时间 Java 中获取当前时间的方法有很多种,下面介绍两种比较常见的方法: 方法一:使用 Date 类 可以使用 Java 中的 Date 类来获取当前时间,代码如下: import java.util.Date; public class GetCurrentTimeDemo { publ…

    Java 2023年5月20日
    00
  • java 字段值为null,不返回该字段的问题

    当Java对象的某个字段的值为null时,在转换为JSON格式或序列化为XML格式时,这个字段将默认不返回。这可能会导致应用程序出现错误,因为其他服务/应用程序可能需要处理该字段并期望它不为null。 下面是解决这个问题的一些攻略: 使用Jackson库 Jackson库是处理JSON格式的一种常见Java库,提供了一个简单的解决方案来处理空值的情况。使用它…

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