netty cpu 占用率 高_「Netty系列」一文熟悉NIO

本文探讨了Netty中的NIO组件,包括Buffer的两种类型、读写模式及其属性,Channel的概念以及与Buffer的配合,以及Selector在高并发场景下的作用和多路复用机制。通过学习,读者可以更好地理解Netty如何实现高效非阻塞IO。
摘要由CSDN通过智能技术生成

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

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

01NIO组件基本介绍

1 Buffer概述(缓冲区)

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

2 Buffer执行原理分析

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

b 写模式

6fc08e75adc2f52b5b027a01d8faf36d.png


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

c 读模式

c3715961cacd122e66f36ed9915fffda.png


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

2 Channnl(通道)

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

2d507aaf666e571065e7b4f55e2dc032.png

3 Selector(选择器)

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

b1919c35dd42eaaedbb7bcfba9eee4f0.png

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

ed54982d77c54cec3f069f48dd08527f.png

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源码。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值