java的IO之NIO

news2024/10/7 12:29:02

NIO是一种同步非阻塞的I/O模型,在Java 1.4中引入了NIO框架,对应java.nio包,提供了channel、selector、buffer等。
NIO中的N可以理解为Non-blocking不在单纯是New,它支持面向缓冲的,基于通道的I/O操作方法。NIO提供了与传统BIO模型中的SocketServerSocket相对应的SocketChannelServerSocketChannel,两种不同的套接字通道实现两种通道都支持阻塞和非阻塞式的两种模式,阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性不好;非阻塞模式刚好相反,对于低负载的、低并发的应用程序,可以使用同步阻塞I/O来提高开发效率和维护性;对于高负载的、高并发的应用,应该使用NIO的非阻塞模式来开发。

NIO

NIO(Non-blocking I/O)是Java中的一种非阻塞式IO模型,它基于缓冲区(Buffer)和通道(Channel)的概念,提供了更高效的IO操作和更好的并发处理能力。NIO模型使用单个线程处理多个IO操作,通过选择器(Selector)来管理多个通道,实现非阻塞的IO操作。

NIO的相关概念和使用方式:

  • 通道(Channel):通道是NIO模型中的基本组件,用于读取和写入数据。通道提供了高效的数据传输能力,并且可以通过非阻塞方式进行IO操作。常见的通道类有FileChannel、SocketChannel和ServerSocketChannel等。

  • 缓冲区(Buffer):缓冲区是NIO模型中用于存储数据的对象。数据从通道读取到缓冲区,或从缓冲区写入到通道。缓冲区提供了对数据的高效访问和操作。常见的缓冲区类有ByteBuffer、CharBuffer和ByteBuffer等。

  • 选择器(Selector):选择器是NIO模型中的关键组件,用于管理多个通道的IO操作。通过选择器,可以将一个线程管理多个通道,实现非阻塞的IO操作。选择器会不断地轮询注册在其上的通道,发现有IO事件发生时进行处理。

  • 使用方式:

    1. 创建通道:通过Channel类的工厂方法创建通道对象,如FileChannel.open()、SocketChannel.open()等。
    2. 创建缓冲区:通过Buffer类的静态方法创建缓冲区对象,如ByteBuffer.allocate()、CharBuffer.allocate()等。
    3. 注册通道:将通道注册到选择器上,通过SelectableChannel.register()方法实现。
    4. 选择就绪通道:通过选择器的select()方法选择就绪的通道,进行相应的IO操作。
    5. 处理IO事件:根据不同的IO事件类型,进行读取、写入或其他操作。
    6. 关闭通道:在完成IO操作后,及时关闭通道,释放资源。

BIO模式的操作

BIO 以流的方式处理数据,面向流的 BIO 一次处理一个字节数据:一个输入流产生一个字节数据,一个输出流消费一个字节数据。为流式数据创建过滤器非常容易,链接几个过滤器,以便每个过滤器只负责复杂处理机制的一部分。不利的一面是,面向流的 I/O 通常相当慢。
请添加图片描述

NIO模式的操作

NIO 以块的方式处理数据,面向块的 NIO 一次处理一个数据块,按块处理数据比按流处理数据要快得多。但是面向块的 NIO 缺少一些面向流的 BIO 所具有的优雅性和简单性。
请添加图片描述

解决的问题:

NIO可以用来解决传统的阻塞IO模型中的一些问题,包括:

  • 高并发处理能力:NIO模型使用单个线程处理多个IO操作,通过选择器(Selector)管理多个通道,实现非阻塞的IO操作。这样可以提高系统的并发处理能力,减少线程数量和资源消耗。
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

public class HighConcurrencyServer {
    public static void main(String[] args) {
        try {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.bind(new InetSocketAddress(8080));
            serverSocketChannel.configureBlocking(false);

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

            while (true) {
                selector.select();

                Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
                while (keyIterator.hasNext()) {
                    SelectionKey key = keyIterator.next();

                    if (key.isAcceptable()) {
                        ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
                        SocketChannel clientChannel = serverChannel.accept();
                        clientChannel.configureBlocking(false);
                        clientChannel.register(selector, SelectionKey.OP_READ);
                    } else if (key.isReadable()) {
                        SocketChannel clientChannel = (SocketChannel) key.channel();
                        ByteBuffer buffer = ByteBuffer.allocate(1024);
                        clientChannel.read(buffer);
                        buffer.flip();
                        //TODO处理读取到的数据
                        // ...

                        clientChannel.close();
                    }

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

  • 资源利用率提升:由于NIO模型使用单个线程处理多个IO操作,可以更有效地利用系统资源,避免了为每个连接创建一个独立线程的资源浪费。
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

public class ResourceUtilizationServer {
    public static void main(String[] args) {
        try {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.bind(new InetSocketAddress(8080));
            serverSocketChannel.configureBlocking(false);

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

            while (true) {
                selector.select();

                Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
                while (keyIterator.hasNext()) {
                    SelectionKey key = keyIterator.next();

                    if (key.isAcceptable()) {
                        ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
                        SocketChannel clientChannel = serverChannel.accept();
                        clientChannel.configureBlocking(false);
                        clientChannel.register(selector, SelectionKey.OP_READ);
                    } else if (key.isReadable()) {
                        SocketChannel clientChannel = (SocketChannel) key.channel();
                        ByteBuffer buffer = ByteBuffer.allocate(1024);
                        clientChannel.read(buffer);
                        buffer.flip();
                        //TODO处理读取到的数据
                        // ...

                        clientChannel.close();
                    }

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

  • 非阻塞IO操作:NIO模型中的IO操作是非阻塞的,即当没有数据可读取时,IO操作不会被阻塞,而是立即返回。这样可以避免线程被长时间阻塞,提高系统的响应性能。
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

public class NonBlockingIOExample {
    public static void main(String[] args) {
        try {
            SocketChannel socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);
            socketChannel.connect(new InetSocketAddress("example.com", 80));

            while (!socketChannel.finishConnect()) {
                //TODO等待连接完成
                //....
            }

            ByteBuffer buffer = ByteBuffer.allocate(1024);
            buffer.put("Hello, Server".getBytes());
            buffer.flip();
            socketChannel.write(buffer);

            buffer.clear();
            socketChannel.read(buffer);
            buffer.flip();
            //TODO处理读取到的数据
            // ...

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

  • 选择器机制:NIO模型通过选择器(Selector)来管理多个通道的IO操作。选择器会不断地轮询注册在其上的通道,发现有IO事件发生时进行处理,避免了传统阻塞式IO模型中需要为每个通道创建一个线程的开销。
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

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

            SocketChannel channel1 = SocketChannel.open();
            channel1.configureBlocking(false);
            channel1.connect(new InetSocketAddress("example.com", 80));
            channel1.register(selector, SelectionKey.OP_CONNECT);

            SocketChannel channel2 = SocketChannel.open();
            channel2.configureBlocking(false);
            channel2.connect(new InetSocketAddress("example.org", 80));
            channel2.register(selector, SelectionKey.OP_CONNECT);

            while (true) {
                selector.select();

                Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
                while (keyIterator.hasNext()) {
                    SelectionKey key = keyIterator.next();

                    if (key.isConnectable()) {
                        SocketChannel channel = (SocketChannel) key.channel();
                        if (channel.isConnectionPending()) {
                            channel.finishConnect();
                        }
                        //TODO 处理连接完成事件
                        // ...
                    }

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

  • 灵活的缓冲区操作:NIO模型使用缓冲区(Buffer)来读取和写入数据,提供了灵活的数据操作方式。可以直接操作缓冲区来读取、写入数据,而无需通过输入流和输出流的方式。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class BufferExample {
    public static void main(String[] args) {
        try {
            FileInputStream fis = new FileInputStream("input.txt");
            FileOutputStream fos = new FileOutputStream("output.txt");

            FileChannel inputChannel = fis.getChannel();
            FileChannel outputChannel = fos.getChannel();

            ByteBuffer buffer = ByteBuffer.allocate(1024);

            while (inputChannel.read(buffer) != -1) {
                buffer.flip();
                outputChannel.write(buffer);
                buffer.clear();
            }

            inputChannel.close();
            outputChannel.close();

            fis.close();
            fos.close();

            System.out.println("文件复制成功.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

NIO和BIO

区别

  • 阻塞 vs 非阻塞:BIO模型是阻塞式IO模型,即当没有数据可读取时,IO操作会被阻塞,直到有数据可读取。而NIO模型是非阻塞式IO模型,当没有数据可读取时,IO操作不会被阻塞,而是立即返回。

  • 线程模型:BIO模型使用一个线程处理一个连接,当有多个连接时,需要创建多个线程,可能导致资源浪费和性能下降。而NIO模型使用单个线程处理多个连接,通过选择器(Selector)管理多个通道,实现非阻塞的IO操作。

  • 缓冲区操作:BIO模型使用字节流或字符流进行数据读写,而NIO模型使用缓冲区(Buffer)进行数据读写,提供了更灵活的数据操作方式。

作用

  • BIO:BIO模型适用于连接数较少、并发要求不高的简单应用场景。它简单易用,可靠性高,适合于对数据完整性和可靠性要求较高的场景。

  • NIO:NIO模型适用于高并发、大规模的应用场景,可以提高系统的并发处理能力和资源利用率。它具有高性能、非阻塞的特性,适合于对并发性能要求较高的场景。

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

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

相关文章

SCI一区 | Matlab实现WOA-TCN-BiGRU-Attention鲸鱼算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测

SCI一区 | Matlab实现WOA-TCN-BiGRU-Attention鲸鱼算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测 目录 SCI一区 | Matlab实现WOA-TCN-BiGRU-Attention鲸鱼算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测预测效果基本介绍模型描述程序…

微信小程序 - picker-viewer实现省市选择器

简介 本文会基于微信小程序picker viewer组件实现省市选择器的功能。 实现效果 实现代码 布局 <picker-view value"{{value}}" bindchange"bindChange" indicator-style"height: 50px;" style"width: 100%; height: 300px;" &…

使用Intellij idea编写Spark应用程序(Scala+Maven)

使用Intellij idea编写Spark应用程序(ScalaMaven) 对Scala代码进行打包编译时&#xff0c;可以采用Maven&#xff0c;也可以采用sbt&#xff0c;相对而言&#xff0c;业界更多使用sbt。这里介绍IntelliJ IDEA和Maven的组合使用方法。IntelliJ IDEA和SBT的组合使用方法&#xf…

牛客题霸-SQL篇(刷题记录二)

本文基于前段时间学习总结的 MySQL 相关的查询语法&#xff0c;在牛客网找了相应的 MySQL 题目进行练习&#xff0c;以便加强对于 MySQL 查询语法的理解和应用。 由于涉及到的数据库表较多&#xff0c;因此本文不再展示&#xff0c;只提供 MySQL 代码与示例输出。 以下内容是…

Xilink 简单双口ram ip的读写仿真

简单双口RAM有两个端口Port A和port B,其中Port A用于写数据&#xff0c;Port B用于读数据&#xff0c;读写接口可以独立时钟工作。这一点和真双口RAM是有区别的&#xff0c;真双口RAM的A B两个Port都可以进行读写操作。 RAM是FPGA中重要的数据结构&#xff0c;可用于数…

EI级!高创新原创未发表!VMD-TCN-BiGRU-MATT变分模态分解卷积神经网络双向门控循环单元融合多头注意力机制多变量时间序列预测(Matlab)

EI级&#xff01;高创新原创未发表&#xff01;VMD-TCN-BiGRU-MATT变分模态分解卷积神经网络双向门控循环单元融合多头注意力机制多变量时间序列预测&#xff08;Matlab&#xff09; 目录 EI级&#xff01;高创新原创未发表&#xff01;VMD-TCN-BiGRU-MATT变分模态分解卷积神经…

阿里云4核16G服务器价格26.52元1个月、149.00元半年,ECS经济型e实例

阿里云4核16G服务器优惠价格26.52元1个月、79.56元3个月、149.00元半年&#xff0c;配置为阿里云服务器ECS经济型e实例ecs.e-c1m4.xlarge&#xff0c;4核16G、按固定带宽 10Mbs、100GB ESSD Entry系统盘&#xff0c;活动链接 aliyunfuwuqi.com/go/aliyun 活动链接打开如下图&a…

【数据挖掘】实验4:数据探索

实验4&#xff1a;数据探索 一&#xff1a;实验目的与要求 1&#xff1a;熟悉和掌握数据探索&#xff0c;学习数据质量分类、数据特征分析和R语言的主要数据探索函数。 二&#xff1a;实验内容 1&#xff1a;数据质量分析 2&#xff1a;统计量分析 3&#xff1a;贡献度分析…

【黄啊码】如何用GPT和向量数据库做问答型AI

知识库服务依赖该数据库&#xff0c;Embedding 形式个性化训练 ChatGPT&#xff0c;必不可少的就是向量数据库 因为 qdrant 向量数据库只支持 Docker 部署&#xff0c;所以需要先安装好 Docker 服务。 命令行安装 拉取镜像 docker pull qdrant/qdrant 运行服务 docker run -…

查立得源码如何去除版权

最近发现很多人百度&#xff1a;查立得源码如何去除版权。 每个源代码/软件都是有版权的&#xff0c;无法去除&#xff0c;我们也得尊重知识产权/劳动成果。 可以去除/修改的是&#xff1a;页面显示的版权信息,查立得底部信息均可自定义(一般conn.php可修改)。 另&#xff1…

图床项目实战:后续开发与优化

在之前的文章中&#xff0c;我们介绍了图床项目的基本实现&#xff0c;接下来&#xff0c;我将提供扩展功能和优化性能的关键代码片段。 一、图片分类管理 首先&#xff0c;我们需要在数据库中创建分类表&#xff0c;并在图片表中添加分类字段。 class Category(db.Model): …

STM32---DHT11采集与BH1750FVI光照传感器(HAL库、含源码)

写在前面&#xff1a;本节我们学习使用两个常见的传感器模块&#xff0c;分别为DHT11温湿度传感器以及BH1750FVI光照传感器,这两种传感器在对于环境监测中具有十分重要的作用&#xff0c;因为其使用简单方便&#xff0c;所以经常被用于STM32的项目之中。今天将使用分享给大家&a…

会员中心微服务

文章目录 1.环境配置1.创建会员中心模块2.检查父子模块的pom.xml1.父模块注意&#xff1a;如果父模块中的依赖显示not found&#xff0c;原因是子模块并没有引用&#xff0c;不用在意 2.子模块 3.pom.xml 引入相关依赖&#xff08;别忘记刷新maven&#xff09;4.application.ym…

【保姆级教程】YOLOv8目标检测:训练自己的数据集

一、YOLOV8环境准备 1.1 下载安装最新的YOLOv8代码 仓库地址&#xff1a; https://github.com/ultralytics/ultralytics1.2 配置环境 pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple二、数据准备 2.1 安装labelme标注软件 pip install label…

主干网络篇 | YOLOv8更换主干网络之GhostNet

前言:Hello大家好,我是小哥谈。GhostNet是2019年由华为诺亚方舟实验室发布的轻量级网络,速度和MobileNetV3相似,但是识别的准确率比MobileNetV3高,在ImageNet ILSVRC2012分类数据集的达到了75.7%的top-1精度。该论文提除了Ghost模块,通过廉价操作生成更多的特征图。基于一…

如何用pytorch调用预训练Swin Transformer中的一个Swin block模块

1&#xff0c;首先&#xff0c;我们需要知道的是&#xff0c;想要调用预训练的Swin Transformer模型&#xff0c;必须要安装pytorch2&#xff0c;因为pytorch1对应的torchvision中不包含Swin Transformer。 2&#xff0c;pytorch2调用预训练模型时&#xff0c;不建议使用pretr…

Uibot6.0 (RPA财务机器人师资培训第3天 )财务招聘信息抓取机器人案例实战

训练网站&#xff1a;泓江科技 (lessonplan.cn)https://laiye.lessonplan.cn/list/ec0f5080-e1de-11ee-a1d8-3f479df4d981https://laiye.lessonplan.cn/list/ec0f5080-e1de-11ee-a1d8-3f479df4d981https://laiye.lessonplan.cn/list/ec0f5080-e1de-11ee-a1d8-3f479df4d981(本博…

基于python+vue成都旅游网flask-django-php-nodejs

本篇论文对成都旅游网的需求分析、功能设计、系统设计进行了较为详尽的阐述&#xff0c;并对系统的整体设计进行了阐述&#xff0c;并对各功能的实现和主要功能进行了说明&#xff0c;并附上了相应的操作界面图。 语言&#xff1a;Python 框架&#xff1a;django/flask 软件版本…

阿里云幻兽帕鲁4核16G和8核32G服务器优惠价格

2024阿里云幻兽帕鲁专用服务器价格表&#xff1a;4核16G幻兽帕鲁专用服务器26元一个月、149元半年&#xff0c;默认10M公网带宽&#xff0c;8核32G幻兽帕鲁服务器10M带宽价格90元1个月、271元3个月。阿里云提供的Palworld服务器是ECS经济型e实例&#xff0c;CPU采用Intel Xeon …