【Spring 篇】走进Java NIO的奇妙世界:解锁高效IO操作的魔法

在这里插入图片描述

欢迎来到Java NIO的神奇之旅!在这个充满活力的世界里,我们将一起揭示Java NIO(New I/O)的奥秘,探索其在高效IO操作中的神奇魔法。无需担心,即使你是Java的小白,也能轻松领略这个强大而灵活的IO框架的魅力。

背景

在计算机科学的世界中,IO(Input/Output)操作一直是不可避免的任务之一。Java早期的IO模型使用的是传统的InputStream和OutputStream,虽然功能强大,但在高并发、大规模IO操作的场景下显得力不从心。随着对性能的要求不断提升,Java NIO应运而生。

走近Java NIO

传统IO的痛点

在传统的IO模型中,每个连接都需要一个独立的线程来处理。这样的模型在连接数较少的情况下可能还能应付,但一旦面对大规模的连接,线程数量的爆发式增长会导致系统资源的枯竭,性能急剧下降。这就好比在繁忙的高速公路上,每辆车都占用一条车道,导致交通拥堵。

Java NIO的亮点

Java NIO引入了一套新的IO模型,通过Channel、Buffer、Selector等概念,使得我们可以更高效地进行IO操作。与传统IO不同,Java NIO采用了非阻塞IO模型,一个线程可以处理多个连接,避免了线程爆炸的问题。这就像是在高速公路上引入了车道划分和交通信号灯,让整个交通系统更加有序。

理解Java NIO的基础概念

在深入研究Java NIO之前,让我们先了解一些基础概念。

Channel

Channel是Java NIO中的基础概念之一,它类似于传统IO中的Stream,但更加强大和灵活。Channel可以被用于读、写、或者同时进行读写操作。不同类型的Channel支持不同的操作,比如FileChannel用于文件操作,SocketChannel用于网络套接字操作等。

Buffer

Buffer是一个内存块,底层实际上是一个数组。数据通过Buffer读取到Channel,或者从Channel写入到Buffer。Buffer提供了对数据的结构化访问,可以更方便地操作数据。

Selector

Selector是Java NIO中的关键组件,它提供了对多个Channel的监控能力。通过Selector,一个线程可以监控多个Channel的IO事件,从而实现单线程处理多个连接的目的。这种机制叫做事件驱动,是Java NIO的核心之一。

实战演练

让我们通过一些实际的例子,来深入理解Java NIO的使用方法。

示例一:使用Channel和Buffer进行文件读写

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class FileCopyWithNIO {

    public static void main(String[] args) {
        try (FileChannel sourceChannel = new FileInputStream("source.txt").getChannel();
             FileChannel destinationChannel = new FileOutputStream("destination.txt").getChannel()) {

            ByteBuffer buffer = ByteBuffer.allocate(1024);

            while (sourceChannel.read(buffer) != -1) {
                buffer.flip(); // 切换为读模式
                destinationChannel.write(buffer);
                buffer.clear(); // 清空缓冲区
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

这里使用了FileChannel和ByteBuffer来实现文件的拷贝操作。通过allocate方法分配一个ByteBuffer,然后使用read方法将数据从源文件读取到缓冲区,再切换为读模式进行写操作。最后,清空缓冲区,准备下一轮读取。

示例二:使用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;

public class NIOServer {

    public static void main(String[] args) {
        try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
             Selector selector = Selector.open()) {

            serverSocketChannel.bind(new InetSocketAddress(8080));
            serverSocketChannel.configureBlocking(false); // 设置为非阻塞模式
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); // 注册接受连接事件

            while (true) {
                if (selector.select() > 0) {
                    Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                    while (iterator.hasNext()) {
                        SelectionKey key = iterator.next();
                        iterator.remove();

                        if (key.isAcceptable()) {
                            // 处理连接请求
                            handleAccept(key);
                        } else if (key.isReadable()) {
                            // 处理读事件
                            handleRead(key);
                        }
                    }
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void handleAccept(SelectionKey key) throws IOException {
        ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
        SocketChannel socketChannel = serverSocketChannel.accept();
        socketChannel.configureBlocking(false);
        socketChannel.register(key.selector(), SelectionKey.OP_READ);
    }

    private static void handleRead(SelectionKey key) throws IOException {
        SocketChannel socketChannel = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int bytesRead = socketChannel.read(buffer);
        if (bytesRead > 0) {
            buffer.flip();
            byte[] data = new byte[buffer.remaining()];
            buffer.get(data);
            String message = new String(data);
            System.out.println("Received message: " + message);
        } else if (bytesRead == -1) {
            // 客户端断开连接
            socketChannel.close();
        }
    }
}

在这个例子中,我们创建了一个简单的NIO服务器,监听在8080端口。通过Selector实现事件驱动的机制,监听接受连接事件和读事件。在handleAccept方法中,当有连接请求时,我们将对应的SocketChannel注册为读事件。在handleRead方法中,我们读取客户端发送的数据并进行处理。

小结

Java NIO为我们提供了更加灵活和高效的IO操作方式,通过Channel、Buffer和Selector的组合,我们能够轻松地处理大规模连接的情况,避免了传统IO模型的瓶颈。本文中,我们深入了解了Java NIO的基本概念,包括Channel、Buffer和Selector等,并通过实际的示例代码演示了如何使用Java NIO进行文件读写和简单服务器的搭建。希望通过这篇文章,你对Java NIO有了更深入的理解,能够在实际项目中灵活运用这些知识,发挥出Java NIO在IO操作中的魔法般的威力。愿你在编程的旅途中,能够越走越远,不断探索更多有趣的技术。

作者信息

作者 : 繁依Fanyi
CSDN: https://techfanyi.blog.csdn.net
掘金:https://juejin.cn/user/4154386571867191

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【pycharm】作为Array查看出现数据无法显示问题(已解决)

【pycharm】作为Array查看出现数据无法显示问题&#xff08;已解决&#xff09; 当我们在调试代码的时候&#xff0c;需要对某个变量进行查看&#xff0c;就如同在matlab中&#xff0c;我们可以直接在工作区对某个变量进行双击查看矩阵变量的具体数值 在这里我遇到一个问题&am…

关于javascript数字精度丢失的解决办法

分析原因 众所周知&#xff0c;在JavaScript中计算两个十进制数的和&#xff0c;有时候会出现令人惊讶的结果&#xff0c;主要原因是计算机将数据存储为二进制所引起的&#xff0c;所以这并不是javascript存在的缺陷&#xff0c;而在其他语言中也有类似的问题。 例如下面的例子…

Java小项目--满汉楼

Java小项目–满汉楼 项目需求 项目实现 1.实现对工具包的编写 先创建libs包完成对jar包的拷贝和添加入库 德鲁伊工具包 package com.wantian.mhl.utils;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource; import java.io.FileInputStream…

Java基础--集合

集合 1.可以动态的保存任意多个对象&#xff0c;使用比较方便。 2.提供了一系列方便的操作对象的方法&#xff1a;add&#xff0c;remove&#xff0c;set&#xff0c;get等。 3.使用集合添加&#xff0c;删除新元素的示意代码&#xff0c;简介明了。 集合主要是两种&#xff0…

c语言扫雷改进版

目录 文章目录 主体 整体架构流程 技术名词解释 技术细节 测试情况 文章目录 概要整体架构流程技术名词解释技术细节测试情况 主体 主体包括菜单&#xff0c;游戏规则简绍&#xff0c;选择进行与否 int main() {int input;srand((unsigned int)time(NULL));do{ menu()…

谷歌地图TMS地图服务地址收集2024,测试可用

对于普通的开发者或者GIS从业者来说&#xff0c;免费的底图影像服务&#xff0c;太重要了。之前写过一篇谷歌地图的TMS地址收集的博文&#xff0c;由于谷歌网站关闭已经不能用。最近又发现了谷歌在国内开放了其他地址&#xff0c;在这里给大家分享一下。 https://gac-geo.googl…

springboot Thymeleaf模版引擎使用

1.引入依赖 <!--thymeleaf视图引擎--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> html中要声明约束&#xff0c;这样就可以使用themelraf视…

EMC Unity存储系统(包含VNXe)常用检查命令

DELL EMC的Unity存储系统&#xff0c;包括VNXe存储系统的OS已经完全和Clariion 的VNX不同了&#xff0c;近期遇到很多关于EMC unity存储系统故障的一些初步检查需求&#xff0c;下面是一些对于DELL EMC Unity存储系统的最常用的底层检查命令&#xff0c;可以对系统故障有个初步…

小程序商城如何接入和设置支付宝支付功能?

众所周知&#xff0c;移动支付已成为电商平台不可或缺的核心组件。为了提升用户体验并拓宽支付渠道&#xff0c;许多小程序商城系统纷纷引入了支付宝作为支付选项。那么&#xff0c;如何在小程序商城系统中成功接入和设置支付宝支付功能呢&#xff1f;这似乎是大家当前所面临的…

电子台账:账页数据溯源

目录 1 前言 2 打开数据溯源面板 3 溯源面板操作 1 前言 账页中让人眼花缭乱的大堆数据来自哪里&#xff1f;从企业数据源表格中自动抓取数据后&#xff0c;如果感觉数据不对&#xff0c;就需要进行核对、排错&#xff0c;怎样确定程序到底抓取的哪些单元格&#xff1f;取数…

Visual Studio 2022 出现:E1696无法打开 源 文件 “stdafx.h“;E0020未定义标识符 “_TCHAR“错误解决办法

今天在用自己电脑上的visual studio2022写并行计算实验报告时出现了这种错误&#xff0c;但我在机房电脑vs2010版本运行时没有任何问题&#xff0c;于是我在网上找了解决办法&#xff0c;现总结如下。 1.报错E1696无法打开 源 文件 "stdafx.h"&#xff0c;解决办法&a…

思维线索(Thread of Thought)-ThoT梳理混乱的语境

Thread of Thought Unraveling Chaotic Contexts 大型语言模型&#xff08;LLMs&#xff09;在自然语言处理领域开启了一个变革的时代&#xff0c;在文本理解和生成任务上表现出色。然而&#xff0c;当面对混乱的上下文环境&#xff08;例如&#xff0c;干扰项而不是长的无关上…

【Java - 框架 - SpringMVC】(01) SpringMVC框架的简单创建与使用,快速上手

"SpringMVC"框架的简单创建与使用&#xff0c;快速上手&#xff1b; 环境 Java版本"1.8.0_202"&#xff1b;Spring Boot版本"2.5.9"&#xff1b;Windows 11 专业版_22621.2428&#xff1b;IntelliJ IDEA 2021.1.3(Ultimate Edition)&#xff1…

NVIDIA NCCL 源码学习(十三)- IB SHARP

背景 之前我们看到了基于ring和tree的两种allreduce算法&#xff0c;对于ring allreduce&#xff0c;一块数据在reduce scatter阶段需要经过所有的rank&#xff0c;allgather阶段又需要经过所有rank&#xff1b;对于tree allreduce&#xff0c;一块数据数据在reduce阶段要上行…

淘宝店铺如何从1688一键铺货?官方授权API接口,可满足多样化上货需求

那么新手卖家如何将1688的源头厂货一键铺货到淘宝店铺呢&#xff1f;下面我教大家几招&#xff1a; 1、通过淘宝复制一键复制上货 淘宝API接口采集 taobao.item_get 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretStr…

无粉乳胶手套:提升操作效率与舒适度的理想选择

作为一种新型的个人防护装备&#xff0c;无粉乳胶手套因其清洁、舒适和高靈敏度的特点&#xff0c;逐渐成为各个行业的首选。本文将通过对比分析无粉乳胶手套与其他手套的差异&#xff0c;探讨其在提升操作效率和舒适度方面的优势。 提升操作效率&#xff1a; 无粉乳胶手套具有…

[C语言]——函数递归

目录 一.什么是递归 1.递归的思想&#xff1a; 二.递归的限制条件 三.递归举例 1.举例1&#xff1a;求n的阶乘 1.1分析和代码实现 1.2画图推演 2.举例2&#xff1a;顺序打印⼀个整数的每⼀位 2.1分析和代码实现 2.2画图推演 四.递归与迭代 1.举例3&#xff1a;求第…

记录一次服务器内存使用率过高达到90%告警问题排查。

目录 一、前言二、问题排查处理三、 结尾 &#x1f469;&#x1f3fd;‍&#x1f4bb;个人主页&#xff1a;阿木木AEcru &#x1f525; 系列专栏&#xff1a;Docker容器化部署系列 &#x1f4b9;每一次技术突破&#xff0c;都是对自我能力的挑战和超越。 一、前言 一大早就有一…

EtherCAT 开源主站 IGH 在 linux 开发板的移植和伺服通信测试

手边有一套正点原子linux开发板imax6ul&#xff0c;一直在吃灰&#xff0c;周末业余时间无聊&#xff0c;把EtherCAT的开源IGH主站移植到开发板上玩玩儿&#xff0c;搞点事情做。顺便学习研究下EtherCAT总线协议及其对伺服驱动器的运动控制过程。实验很有意思&#xff0c;这里总…

01mysql

登陆mysql 默认数据库 进入&#xff0c;展示&#xff0c;删除 &#xff0c;查看当前正使用的库 select version()查看版本 查看表结构desc 查询 not in不会忽略空 in会自动忽略 like模糊查询 %o%中间带o的 _A%第二个字母是A的 查名字是下划线的 %\_% 排序 order …