NIO编程学习笔记(一)

NIO的概述

简介

IO与NIO的区别

什么是面向流?什么是面向缓冲区?

NIO的三大组件

Channel(通道)&&Buffer(缓冲区)

Selector(选择器)

案例实现(三大组件的基本使用)


NIO的概述

简介

NIO全称是non-blocking io,即非阻塞IO

Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API。NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同,NIO支持面向缓冲区的、基于通道的IO操作。NIO将以更加高效的方式进行文件的读写操作。

IO与NIO的区别

IONIO
面向流(Stream Oriented)面向缓冲区(Buffer Oriented)
阻塞IO(Blocking IO)非阻塞IO(NonBlocking IO)
选择器(Selectors)

什么是面向流?什么是面向缓冲区?

传统IO在传输数据时,根据输入输出的不同需要分别建立不同的链接,而且传输的数据是以的形式在链接上进行传输的。

就像自来水要通过水管将自来水厂和家连接起来一样,如图:

NIO在传输数据时,会在输入输出端之间建立通道,然后将数据放入到缓冲区中。缓冲区通过通道来传输数据

这里通道就像是铁路,能够连通两个地点。缓冲区就像是火车,能够真正地进行数据的传输。

简单的来说就是不用建立两个通道了。

NIO的三大组件

Channel(通道)&&Buffer(缓冲区)

NIO有三大组件,其中最为核心的就是ChannelBuffer

Channel有一点类似于Stream,它就是读写数据的双向通道,可以从Channel将数据读入Buffer,也可以将Buffer的数据写入Channel,而之前的Stream要么是输入,要么是输出,Channel要比Stream更加底层。

简而言之就是,通道负责传输,缓冲区负责存储。

常见的Channel有:

  • FileChannel
  • DatagramChannel
  • SocketChannel
  • ServletSocketChannel

常见的Buffer有:

  • ByteBuffer(MappedByteBuffer、DirectByteBuffer、HeapByteBuffer)
  • CharBuffer
  • ShortBuffer
  • IntBuffer
  • LongBuffer
  • FloatBuffer
  • DoubleBuffer

Selector(选择器)

选择器来形容它可能会有一点抽象。

最初我们开发服务器的时候是使用多线程进行设计的。

缺点:

  • 内存占用高

  • 线程上下文切换成本高

  • 只适合连接数少的场景

之后我们引入了线程池的概念

缺点:

  • 阻塞模式下,线程仅能处理一个 socket 连接

  • 仅适合短连接场景

Selector设计服务器

selector 的作用就是配合一个线程来管理多个 channel,获取这些 channel 上发生的事件,这些 channel 工作在非阻塞模式下,不会让线程吊死在一个 channel 上。适合连接数特别多,但流量低的场景(low traffic)

案例实现(三大组件的基本使用)

简单的使用了一下

public class NIO_demo01 {
    public static void main(String[] args) {
        try {
            // 文件的channel作为数据的读写通道
            FileChannel channel = new FileInputStream("data.txt").getChannel();
            //准备缓冲区 allocate() 缓冲区大小
            ByteBuffer buffer = ByteBuffer.allocate(10);
            while (true) {
                // 从channel读取数据,向buffer写入
                int len = channel.read(buffer);
                // 没有内容了
                if (len == -1) {
                    break;
                }
                
                // 切换至读模式
                buffer.flip();

                // 检查是否有剩余的数据
                while (buffer.hasRemaining()) {
                    // 一次读一个字节
                    byte b = buffer.get();
                    System.out.println((char)b);
                }
                // 切换为写模式
                buffer.clear();
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}

可以实现从本地的data.txt文件中读取数据。

posted @   金鳞踏雨  阅读(17)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示