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

news2024/9/25 1:23:42

在这里插入图片描述

欢迎来到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

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

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

相关文章

如何设置IDEA远程连接服务器开发环境并结合cpolar实现ssh远程开发

文章目录 1. 检查Linux SSH服务2. 本地连接测试3. Linux 安装Cpolar4. 创建远程连接公网地址5. 公网远程连接测试6. 固定连接公网地址7. 固定地址连接测试 本文主要介绍如何在IDEA中设置远程连接服务器开发环境&#xff0c;并结合Cpolar内网穿透工具实现无公网远程连接&#xf…

SpringBoot+Vue前后端分离项目在Linux系统中基于Docker打包发布

文章目录 SpringBootVue前后端分离项目在Linux系统中基于Docker打包发布一、Java项目基于Docker打包发布1.打包应用&#xff0c;将打好的jar包放到我们的linux系统中2.新建dockerfile3.打包镜像4.测试运行5.上传镜像到阿里云免费私仓 二、Vue项目打包到docker镜像1.编译打包前端…

记一次由于buff/cache导致服务器内存爆满的问题

目录 前言 复现 登录服务器查看占用内存进程排行 先了解一下什么是buff/cache&#xff1f; 尝试释放buffer/cache /proc/sys/vm/drop_caches dirty_ratio dirty_background_ratio dirty_writeback_centisecs dirty_expire_centisecs drop_caches page-cluster swap…

罗技G29游戏方向盘试玩拆解,带震动力反馈

1.正好有时间记录下 自己的爱好 一千多的罗技G29游戏方向盘试玩拆解&#xff0c;带震动力反馈&#xff0c;值这个价吗_哔哩哔哩_bilibili 一千多的罗技G29游戏方向盘试玩拆解&#xff0c;带震动力反馈&#xff0c;值这个价吗_哔哩哔哩_bilibili 2.拆解 3.2个大电机 4.主控芯…

智能模型新篇章:RAG + Fine-Tuning 混合增强策略

一、前言 在之前的探讨中&#xff0c;我们已经分别深入了解了RAG&#xff08;检索增强生成&#xff09;和 Fine-tuning&#xff08;微调&#xff09;这两种优化大型语言模型的方法&#xff0c;探讨了它们在不同业务场景下的适用性、优势及局限。然而&#xff0c;我们很少讨论将…

深度学习——微积分基础

目录 1、导数和微分 1.1 定义函数&#xff1a; 1.2 趋近过程&#xff1a; 1.3 绘图表示&#xff1a; 2、偏导数 3、梯度 4、链式法则 5、学习心得 在2500年前&#xff0c;古希腊人把一个多边形分成三角形&#xff0c;并把它们的面积相加&#xff0c;才找到计算多边形面积…

【记录39】html element-ui 加载

环境 html使用element-ui组件、用vue框架搭建 方法一&#xff1a; 方法二&#xff08;推荐&#xff09; 将相关资源下载下来&#xff0c;在对应的html文件中相对路径引入。注意&#xff1a;css加载放在js之前

Windows 11 鼠标右键可选择 cmd 命令行选项

** Windows 11 鼠标右键可选择 cmd 命令行选项 ** 在文件夹内打开命令行&#xff0c;只能使用 Windows 自带的 PowerShell &#xff0c; 作为一个 cmd 重度使用用户来说很是折磨&#xff0c;需要打开 cmd 然后切换盘符再 cd 。。。 现在咱们自己创建一个可以打开 cmd 的方法…

【C++庖丁解牛】stack的介绍和使用 | queue的介绍和使用 | priority_queue的介绍和使用

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 1. stack的介绍和使用1.1…

微信小程序外卖跑腿点餐(订餐)系统(uni-app+SpringBoot后端+Vue管理端技术实现)

项目介绍 自从计算机发展开始&#xff0c;计算机软硬件相关技术的发展速度越来越快&#xff0c;在信息化高速发展的今天&#xff0c;计算机应用技术似乎已经应用到了各个领域。 在餐饮行业&#xff0c;除了外卖以外就是到店里就餐&#xff0c;在店里就餐如果需要等待点餐的话…

VUE2 Day08智慧商城案例

shift alt f 格式化代码快捷键 vant组件库的安装 安装出错在指令后面加 --force 安装出错在指令后面加 --force **封装api模块的好处&#xff1a; 请求与页面逻辑分离相同的请求可以直接复用请求进行了统一管理** ![在这里插入图片描述](https://img-blog.…

c语言扫雷改进版

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

Linux--gdb调试

一.安装gdb sudo apt install gdb 二.使用gdb 三.gdb的相关操作 gdb 可执行文件名 显示代码: l 加断点: b 行号 启动程序:r(运行之前一定要加断点) 查看断点信息: info break/info b 删除断点信息:delete 断点编号 单步执行:n 打印 :p 显示:display 变量名: 退出:q …

Vue字符串里的中文数字转换为阿拉伯数字

js字符串里的汉字数字转化为数字 <template><view><view><view class"inpbox" ><textarea v-model"voiceMane" input"convert" ></textarea></view></view></view> </template> &…

清华大模型ChatGLM3部署初体验

正文共&#xff1a;1555 字 17 图&#xff0c;预估阅读时间&#xff1a;2 分钟 ChatGLM3是智谱AI和清华大学KEG实验室联合发布的对话预训练模型。该项目在GitHub的工程链接为&#xff1a; https://github.com/THUDM/ChatGLM3 在人工智能领域中&#xff0c;类似“3B”、“6B”、…

Springboot+Vue前后端分离的个人博客系统

项目介绍 进入二十一世纪&#xff0c;以Internet为核心的现代网络积水和通信技术已经得到了飞速的发展和广泛的应用&#xff0c;各种网络交流互动工具也应运而生。其中以论坛、博客、社区、空间最为受广大网民朋友的欢迎&#xff0c;也是目前为止发展的比较成熟的信息交流工具…

【RAG实践】基于 LlamaIndex 和Qwen1.5搭建基于本地知识库的问答机器人

什么是RAG LLM会产生误导性的 “幻觉”&#xff0c;依赖的信息可能过时&#xff0c;处理特定知识时效率不高&#xff0c;缺乏专业领域的深度洞察&#xff0c;同时在推理能力上也有所欠缺。 正是在这样的背景下&#xff0c;检索增强生成技术&#xff08;Retrieval-Augmented G…

Linux第81步_使用“互斥体”实现“互斥访问”共享资源

1、创建MyMutexLED目录 输入“cd /home/zgq/linux/Linux_Drivers/回车” 切换到“/home/zgq/linux/Linux_Drivers/”目录 输入“mkdir MyMutexLED回车”&#xff0c;创建“MyMutexLED”目录 输入“ls回车”查看“/home/zgq/linux/Linux_Drivers/”目录下的文件和文件夹 2、…

el-table树形数据序号排序处理

1&#xff0c;用下面这个代码可以实现基本表格的序号排序 <el-table-column label"序号" width"50px" align"center"><template slot-scope"scope">{{ scope.$index 1 }}</template></el-table-column>2&…

Linux-线程同步

文章目录 前言一、为什么要线程同步&#xff1f;二、线程同步pthread_cond_initpthread_cond_destroypthread_cond_wait、pthread_cond_signal和 pthread_cond_broadcast 三、示例代码 前言 上节课学习了线程互斥&#xff0c;这节课针对线程互斥内容在做进一步的补充和完善&am…