「Netty系列」一文熟悉NIO(Netty前置三)

本文详细介绍了Java NIO的三大核心组件——Buffer、Channel和Selector。Buffer是NIO的基础,分为直接缓冲区和堆字节缓冲区,具有写模式和读模式。Channel类似于流,但支持双向传输,通常与Buffer配合使用。Selector允许单个线程处理多个通道,适合高并发场景,有效减少线程创建和切换成本。同时,文章提供了一个简单的NIO实例。

正常下班,文章走起。通过前面几篇文章对网络基础知识和网络编程有了认识。接下来这篇文章表述和Netty更加息息相关的知识-NIO。每天学习一小时,期待质变来临。

NIO又称为非阻塞IO,是JDK1.4提出的新的IO模型。

01

NIO组件基本介绍

1 Buffer概述(缓冲区)

按照物理分区:直接缓冲区和堆字节缓冲区。
Buffer模式:写模式和读模式 。

2 Buffer执行原理分析

    三个属性(Buffer的三个属性)capacity(容量)、position(位置)、limit(限制)

    b 写模式

        capacity:数组中可以存储元素的个数
        position:下一次可插入元素位置,默认值为0,每添加一个元素都向后移动一位,最大值:capacity - 1
        limit:在写的模式下,limit表示第一个不可写的位置(默认第一个不可写的位置,应该是数组容量值得下一个位置,即默认值为capacity)

    c 读模式
        capacity:数组中可以存储元素的格数。
        position:Buffer由写模式变化为读模式,position会从置0,在进行读取数据时,position向前移动到下一个可读的位置。
          limit:第一个不可读位置,当写模式切换到读模式,limit设置写模式下的position值。即能读到之气那所有写入的数据。

2 Channnl(通道)

概述类似于流进行数据传输,但是和流不同。流是单向的,大部分功能比较单一,要么进行读要么进行写。通道的使用必须要结合Buffer。

3 Selector(选择器)

概述 每一个通道都存在一个线程对其处理。在高并发情况下,就会存在很多通道,就会创建很多线程对象,造成内存占用率升高,增加cpu在多个线程之间切换的时间。因此不使用高并发场景下。

NIO使用通道的改良
我一个线程处理多个任务通道的任务的机制,在NIO中成为多路复用。使用后IO复用后,只需一个线程能对多个通道进行处理,对于高并发的业务场景有优势。补充如下:
线程数随着通道多少进行动态的增减来进行适配。多路复用的核心目的使用最少的线程数去操作更多的通道。创建线程的个数根据通道个数来决定。每注册1023个通道就创建一个线程

02

 NIO实例

public class SocketNioServer {

    public static void main(String[] args) throws Exception {
        //定义通道
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //绑定地址
        serverSocketChannel.bind(new InetSocketAddress("127.0.0.1", 8080));
        //设置为非阻塞模式
        serverSocketChannel.configureBlocking(false);
        //开启一个选择器
        Selector selector = Selector.open();
        //注册
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        while (true) {
            System.out.println("等待连接,阻塞中.....");
            int count = selector.select();
            if (count != 0) {
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                //遍历集合
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while (iterator.hasNext()) {
                    SelectionKey selectionKey = iterator.next();
                    //客户端已经连接,尚未发送数据
                    if (selectionKey.isAcceptable()) {
                        System.out.println("客户端已经连接,尚未发送数据....");
                        //获取通道
                        ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel();
                        SocketChannel socketChannel = ssc.accept();
                        //设置非阻塞
                        socketChannel.configureBlocking(false);
                        //注册到选择器
                        socketChannel.register(selector, SelectionKey.OP_READ);
                    }
                    //任务就绪
                    else if (selectionKey.isReadable()) {
                        System.out.println("客户端成功发送数据");
                        //获取通道
                        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                        //读取信息
                        ByteBuffer buffer = ByteBuffer.allocate(1024);
                        int read = socketChannel.read(buffer);
                        while (read > 0) {
                            //切换缓冲区的模式
                            buffer.flip();
                            System.out.println(new String(buffer.array(), 0, read));
                            //清除缓冲区
                            buffer.clear();
                            read = socketChannel.read(buffer);
                        }
                        socketChannel.close();//释放资源
                    }
                    iterator.remove();
                }
            }
        }
    }
}

 

END

 

公众号简介

在上班之余,学习黑马架构课程一段时间了。持续的分享一些干货,如:Netty、MySQL、缓存、中间件、中台、自动化部署、设计模式、JVM、Spring源码、MyBatis源码。如果你想对该公众号有深入了解,在公众号回复【故事】。

公众号福利

关注公众号,回复【架构面试】,获取架构课程面试题。如果有任何建议或者想说的话,请直接向公众号发消息。运营小姐姐看到后会立即处理。烦请耐心等待!蟹蟹!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值