什么是NIO

NIO(New Input/Output),也称为Java非阻塞IO,是从Java 1.4版本开始引入的一个新的IO API,旨在提供一种比传统的阻塞IO更高效、更灵活的IO操作方式。


一 NIO用法的详细介绍

NIO支持面向缓冲区的、基于通道的IO操作,其核心组件包括缓冲区(Buffer)、通道(Channel)和选择器(Selector)。

1.1 缓冲区(Buffer)

缓冲区是NIO中用于存储数据的对象,它是一个固定大小的内存区域,可以用来读取数据和写入数据。NIO提供了多种类型的缓冲区,如ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer和DoubleBuffer等,用于存储不同类型的数据。

缓冲区的主要属性和方法包括:

  • 容量(Capacity):表示缓冲区可以存储的最大数据量,一旦声明就不能改变。
  • 限制(Limit):表示缓冲区中可以操作数据的大小(limit后面的数据不能读写)。
  • 位置(Position):表示缓冲区中正在操作数据的位置。
  • 标记(Mark):表示记录当前position的位置,可以通过reset()恢复到mark的位置。

缓冲区的主要方法有:

  • put():向缓冲区中写入数据。
  • get():从缓冲区中读取数据。
  • flip():将缓冲区的界限设置为当前位置,并将当前位置重置为0,用于切换读写模式。
  • rewind():将位置重置为0,取消设置的mark。
  • clear():清空缓冲区,但不清空数据,准备下一次读写操作。

1.2 通道(Channel)

通道是NIO中用于数据读写的通道,它可以与文件、网络套接字等进行交互。通道是双向的,既可以用于读操作也可以用于写操作,并且支持非阻塞模式。与传统的IO流不同,通道与缓冲区配合使用,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。

NIO中主要的通道类型有:

  • FileChannel:用于文件的读写操作。
  • SocketChannel:用于网络套接字的读写操作(TCP协议)。
  • ServerSocketChannel:用于监听传入的TCP连接。
  • DatagramChannel:用于UDP数据包的发送和接收。

1.3 选择器(Selector)

选择器是NIO的一个核心组件,它允许单个线程同时处理多个通道(Channel)的IO事件。通过选择器,可以监听多个通道的状态变化(如连接打开、数据到达等),并在这些事件发生时进行相应的处理。这样,一个线程就可以管理多个网络连接,提高了系统的并发性能。

使用选择器的一般步骤包括:

  1. 打开选择器。
  2. 将通道注册到选择器上,并指定要监听的事件类型(如读就绪、写就绪等)。
  3. 调用选择器的select()方法,该方法会阻塞,直到有一个或多个通道发生了注册的事件。
  4. 遍历选择器的已选择键集合(SelectedKeySet),对每个键进行处理。
  5. 更新键的状态,并可能重新注册感兴趣的事件。

NIO通过缓冲区、通道和选择器提供了一种高效、灵活的IO操作方式。它适用于需要处理大量并发连接的网络编程和高性能服务器开发等场景。通过合理地使用缓冲区、通道和选择器,可以显著提高系统的并发性能和吞吐量。


二 对NIO优缺点的详细介绍

NIO(New Input/Output)作为Java中一种新的IO处理方式,相较于传统的BIO(Blocking Input/Output)具有一系列的优点,但同时也存在一些潜在的缺点。

2.1 优点

  • 非阻塞IO:
    NIO最大的优点之一就是其支持非阻塞IO操作。在传统的BIO中,当一个线程进行IO操作时,如果该操作需要等待(如等待数据从网络到达),则该线程会被阻塞,直到IO操作完成。而在NIO中,线程可以在等待IO操作完成时继续执行其他任务,从而提高了系统的资源利用率和吞吐量。
  • 选择器(Selector)机制:
    NIO引入了选择器的概念,允许单个线程同时处理多个通道(Channel)的IO事件。通过选择器,我们可以注册多个通道并监听它们的事件(如读就绪、写就绪等),当某个通道的事件发生时,选择器会通知我们,然后我们可以对这些事件进行处理。这种方式极大地减少了线程的数量,降低了线程切换的开销。
  • 缓冲区(Buffer)的使用:
    NIO通过缓冲区来处理数据,这减少了直接对IO资源的操作次数。数据首先被读入缓冲区,然后再从缓冲区中读取或写入到通道中。缓冲区可以重复使用,减少了内存分配和回收的开销。
  • 更高的并发性能:
    由于NIO支持非阻塞IO和选择器机制,因此它可以在单个线程中处理多个连接,从而提高了系统的并发处理能力。这使得NIO成为构建高性能网络服务器和客户端的理想选择。
  • 更灵活的IO操作:
    NIO提供了更灵活的IO操作方式,如文件映射(File Mapping)和内存映射文件(Memory-Mapped File)等。这些特性使得NIO在处理大文件和网络IO时更加高效。

2.2 缺点

  • 学习曲线较陡:
    相对于传统的BIO,NIO的API更加复杂,需要更多的时间来学习和掌握。这包括理解缓冲区、通道和选择器的概念以及它们之间的关系。
  • 编程复杂度较高:
    由于NIO提供了更多的灵活性和控制能力,因此在使用NIO进行编程时需要更多的代码和逻辑来处理各种情况。这可能会增加程序的复杂度和出错的可能性。
  • 缓冲区管理:
    缓冲区管理是NIO中的一个重要方面,但也是一个潜在的缺点。程序员需要负责缓冲区的分配、使用和释放,这可能会引入内存泄漏等问题。此外,缓冲区的大小也需要根据实际应用场景进行仔细的选择和调整。
  • 性能调优:
    为了充分利用NIO的性能优势,需要对缓冲区大小、线程数量、选择器使用等进行仔细的性能调优。这可能需要一定的时间和经验来找到最优的配置。
  • 兼容性:
    在某些情况下,NIO可能与现有的基于BIO的库或框架不兼容。这可能会增加迁移或集成现有系统的难度和成本。

总的来说,NIO作为Java中一种新的IO处理方式,具有显著的性能优势和灵活性。然而,它也带来了一定的学习曲线和编程复杂度。因此,在选择使用NIO时,需要根据实际应用场景和需求进行权衡和考虑。


三 NIO网络编程示例

NIO(New Input/Output)网络编程通常涉及到非阻塞的IO操作,这使得单个线程可以管理多个网络连接。以下是一个更完整的NIO网络编程示例,包括一个简单的服务器和客户端。这个示例将展示如何使用Selector来同时处理多个客户端的连接和数据读取。

服务器端

import java.io.IOException;  
import java.net.InetSocketAddress;  
import java.nio.ByteBuffer;  
import java.nio.channels.SelectionKey;  
import java.nio.channels.Selector;  
import java.nio.channels.ServerSocketChannel;  
import java.nio.channels.SocketChannel;  
import java.util.Iterator;  
import java.util.Set;  public class NIOServer {  public static void main(String[] args) throws IOException {  Selector selector = Selector.open();  // 打开ServerSocketChannel  ServerSocketChannel serverChannel = ServerSocketChannel.open();  serverChannel.configureBlocking(false);  // 绑定端口并监听  serverChannel.socket().bind(new InetSocketAddress(8000));  // 注册到selector,监听ACCEPT事件  serverChannel.register(selector, SelectionKey.OP_ACCEPT);  // 缓冲区  ByteBuffer buffer = ByteBuffer.allocate(1024);  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();  if (key.isAcceptable()) {  // 接受新的连接  ServerSocketChannel server = (ServerSocketChannel) key.channel();  SocketChannel client = server.accept();  client.configureBlocking(false);  client.register(selector, SelectionKey.OP_READ);  System.out.println("Accepted new connection from " + client);  } else if (key.isReadable()) {  // 读取数据  SocketChannel client = (SocketChannel) key.channel();  buffer.clear();  int bytesRead = client.read(buffer);  if (bytesRead > 0) {  buffer.flip();  byte[] data = new byte[buffer.remaining()];  buffer.get(data);  String received = new String(data, "UTF-8");  System.out.println("Received: " + received);  // 这里可以添加将数据写回客户端的逻辑  }  }  keyIterator.remove();  }  }  }  
}

客户端

import java.io.IOException;  
import java.net.InetSocketAddress;  
import java.nio.ByteBuffer;  
import java.nio.channels.SocketChannel;  public class NIOClient {  public static void main(String[] args) throws IOException {  // 打开SocketChannel  SocketChannel client = SocketChannel.open();  client.configureBlocking(false);  // 连接到服务器  client.connect(new InetSocketAddress("localhost", 8000));  // 等待连接完成  while (!client.finishConnect()) {  // 这里可以做一些其他事情,比如处理其他IO操作  }  // 发送数据到服务器  String newData = "Hello from Client";  ByteBuffer buffer = ByteBuffer.wrap(newData.getBytes("UTF-8"));  while (buffer.hasRemaining()) {  client.write(buffer);  }  // 关闭SocketChannel  client.close();  }  
}

注意:

  • 这个服务器示例在接收到数据后并没有将数据写回客户端。在实际应用中,你可能需要添加这样的逻辑来响应客户端的请求。
  • 客户端在发送完数据后立即关闭了SocketChannel。在实际应用中,你可能希望保持连接以接收服务器的响应或进行进一步的通信。
  • 服务器端在接收到数据后,会将其转换为字符串并打印出来。在生产环境中,你可能需要处理多种类型的数据和更复杂的协议。
  • 这个示例没有处理异常和关闭资源(如Selector和ServerSocketChannel)的逻辑。在实际应用中,你应该在适当的时机关闭这些资源,并处理可能出现的异常。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/875536.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浏览器的最大并发数(http1.1)

HTTP/1.1&#xff1a;每个资源请求通常需要单独的TCP连接&#xff0c;尽管支持Keep-Alive机制&#xff0c;允许在同一个TCP连接上连续发送多个请求。但通常浏览器限制并发TCP连接数&#xff08;例如&#xff0c;每个域名最多6个并发连接&#xff09;。 HTTP/2&#xff1a;引入…

HarmonyOS三方库的使用

系统组件难以提供比较优秀的界面&#xff0c;需要第三方库来实现一些比较好看的界面效果 三方库的获取&#xff1a; 开源社区支持OpenHarmony-TPC 和 Openharmony三方库中心仓 先目前已经拥有各种各样的三方库&#xff0c;包括UI 图片 动画 网络 数据存储 工具类 多媒体 安全等…

leetcode 2236.判断根节点是否等于字节点

1.题目要求: 给你一个 二叉树 的根结点 root&#xff0c;该二叉树由恰好 3 个结点组成&#xff1a;根结点、左子结点和右子结点。如果根结点值等于两个子结点值之和&#xff0c;返回 true &#xff0c;否则返回 false 。2.思路: 直接数组前序遍历&#xff0c;然后判断后面两个…

unity美术资源优化(资源冗余,主界面图集过多)

图片资源冗余&#xff1a; UPR unity的性能优化工具检查资源 1.检查纹理读/写标记 开启纹理资源的读/写标志会导致双倍的内存占用 检查Inspector -> Advanced -> Read/Write Enabled选项 2.检查纹理资源alpha通道 如果纹理的alpha通道全部为0&#xff0c;或者全部为2…

UEFI DebugLib 介绍

1.我们调试中常用Debug 打印信息&#xff0c;这些会输出到BIOS串口日志中 EFI_STATUSEFIAPIHelloWorld2(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE *SystemTable){EFI_STATUS Status;StatusEFI_SUCCESS;gST->ConOut->OutputString(gST->ConOut,L&q…

【vluhub】zabbix漏洞

介绍&#xff1a; zabbix是对服务器资源状态例如、内存空间、CPU、程序运行状态进行检测、设置预警值、短信设置等功能等一款开源工具。配置不当存在未授权,SQL注入漏洞 弱口令 nameadmin&passwordzabbix nameguest&password POST /index.php HTTP/1.1 Host: 192.1…

Flex布局中元素主轴上平均分布 多余的向左对齐

content&#xff1a;父元素 content-item: 子元素 主轴上子元素平均分布 .content {display: flex;flex-wrap: wrap;justify-content: space-between;.service-item {display: flex;flex-direction: column;justify-content: center;align-items: center;width: 80px;height:…

【C++】19.红黑树模拟实现 set 和 map

我们想要实现STL中的set和map&#xff0c;那么第一步就需要看一下库函数是如何实现的&#xff1a; 通过查看源代码我们发现两个容器都包含了stl_tree.h&#xff0c;因此我们猜测此头文件实现的是红黑树。 但是set和map很显然不是使用同一棵树实现的&#xff0c;那么STL库是怎么…

vue3 Axios封装使用

先安装axios&#xff1a; npm install axios 第一步&#xff1a;项目src下创建一个名为request的文件夹&#xff08;看一下示例图&#xff09;&#xff1a; 然后在request下创建两个api.ts和index.ts的文件 api.ts里的内容&#xff1a;&#xff08;url写你自己的接口&#xff…

Vscode——如何快速搜索项目工程中的某个文件的位置

第一步&#xff1a;按 shift ctrl p 第二步&#xff1a;然后把 > 删除 第三步&#xff1a;输入文件名称即可

飞书群聊机器人自定义机器人接入,并实现艾特@群成员功能

飞书群聊机器人还是比钉钉的要麻烦一点&#xff0c;钉钉的直接通过手机号就可以艾特群里面的人&#xff0c;但是飞书的要想艾特群里面的人&#xff0c;需要使用用户的 Open ID 或 User ID。这两个ID怎么获取呢&#xff1f;还需要在飞书的开放平台上创建一个应用&#xff0c;然后…

《Java初阶数据结构》----6.<优先级队列之PriorityQueue底层:堆>

前言 大家好&#xff0c;我目前在学习java。之前也学了一段时间&#xff0c;但是没有发布博客。时间过的真的很快。我会利用好这个暑假&#xff0c;来复习之前学过的内容&#xff0c;并整理好之前写过的博客进行发布。如果博客中有错误或者没有读懂的地方。热烈欢迎大家在评论区…

使用FileZilla Cilent快速让手机与电脑进行文件互传(无需生态)

目录 前言使用 FileZilla笔者的话 前言 当设备多的时候文件的传输就成了一种问题。 就比如说我想将手机上的文件传到电脑里面&#xff0c;因为我使用的电脑跟我的手机不是一个生态的&#xff0c;它们唯一的联系或许就是连接到了统一 WIFI 下&#xff0c;也就是说它们在同一个…

【React】全面解析:从基础知识到高级应用,掌握现代Web开发利器

文章目录 一、React 的基础知识1. 什么是 React&#xff1f;2. React 的基本概念3. 基本示例 二、React 的进阶概念1. 状态&#xff08;State&#xff09;和属性&#xff08;Props&#xff09;2. 生命周期方法&#xff08;Lifecycle Methods&#xff09;3. 钩子&#xff08;Hoo…

计算存储背景与发展

随着云计算、企业级应用以及物联网领域的飞速发展&#xff0c;当前的数据处理需求正以前所未有的规模增长&#xff0c;以满足存储行业不断变化的需求。这种增长导致网络带宽压力增大&#xff0c;并对主机计算资源&#xff08;如内存和CPU&#xff09;造成极大负担&#xff0c;进…

TikTok养号的网络环境及相关代理IP知识

TikTok作为一个流行的短视频分享平台&#xff0c;其用户量非常庞大&#xff0c;很多商家和个人都会使用TikTok来进行引流和推广。由于TikTok的规则和政策限制了每个用户每天发布视频的数量&#xff0c;因此许多用户会使用多个账号来发布更多的视频以提高曝光率。 然而&#xff…

Oracle中LISTAGG 函数的介绍以及使用详情

LISTAGG 函数介绍 listagg 函数是 Oracle 11.2 推出的新特性。 其主要功能类似于 wmsys.wm_concat 函数&#xff0c; 即将数据分组后&#xff0c; 把指定列的数据再通过指定符号合并。 LISTAGG 使用 listagg 函数有两个参数&#xff1a; 1、 要合并的列名 2、…

一种多策略改进鹅智能优化算法IGOOSE(2024年新出优化算法) 种群初始化精英反向策略+非线性下降因子+黄金正弦变异策略

一种多策略改进鹅智能优化算法IGOOSE&#xff08;2024年新出优化算法&#xff09; 种群初始化精英反向策略非线性下降因子黄金正弦变异策略 文章目录 前言一种多策略改进鹅智能优化算法IGOOSE&#xff08;2024年新出优化算法&#xff09; 种群初始化精英反向策略非线性下降因子…

游泳耳机品牌哪个牌子好?四大高热度游泳耳机综合分析

近年来&#xff0c;游泳耳机的受欢迎程度呈指数级增长&#xff0c;市场热度不断攀升。但作为一名长期关注运动科技的专业人士&#xff0c;我必须提醒大家&#xff0c;在享受水下音乐的同时&#xff0c;也要注意选择专业可靠的产品。市面上许多所谓的“游泳耳机”其实缺乏必要的…

【C++】:红黑树深度剖析 --- 手撕红黑树!

目录 前言一&#xff0c;红黑树的概念二&#xff0c;红黑树的性质三&#xff0c;红黑树节点的定义四&#xff0c;红黑树的插入操作4.1 第一步4.2 第二步4.3 插入操作的完整代码 五&#xff0c;红黑树的验证六&#xff0c;实现红黑树的完整代码五&#xff0c;红黑树与AVL树的比较…