>>分享Java编程技术,对《Java面向对象编程》等书籍提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 14458 个阅读者 刷新本主题
 * 贴子主题:  NIO模式的IO多路复用底层原理 回复文章 点赞(0)  收藏  
作者:mary    发表时间:2021-06-24 03:14:32     消息  查看  搜索  好友  邮件  复制  引用

产生缘由

  因为BIO存在线程阻塞,伪异步的话也会存在线程安全和资源浪费情况,而NIO恰好能解决这些问题。

底层原理关键词

1)面向与缓冲区

2)基于通道实现非阻塞式io

3)多路io复用实现(选择器)
            点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小        
   通道(Channel)----TCP链接道路

通常我们nio所有的操作都是通过通道开始的,所有的通道都会注册到统一个选择器(Selector)上实现管理,在通过选择器将数据统一写入到 buffer中。

缓冲区(Buffer)------加快数据的读取

Buffer本质上就是一块内存区,可以用来读取数据,也就先将数据写入到缓冲区中、在统一的写入到硬盘上。

选择器(Selector)------通道的管理,实现多路IO复用机制---一个线程处理多个TCP请求。

Selector可以称做为选择器,也可以把它叫做多路复用器,可以在单线程的情况下可以去维护多个Channel,也可以去维护多个连接;

线程--完成具体的业务
            点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小        

Nio技术多路IO复用底层实现原理

多路:实际指的就是多个不同的tcp连接

复用:一个线程可以维护多个不同的io操作

好处: 占用cpu资源非常小、保证线程安全问题

手写伪NIO代码

public class SocketNioTcpServer {
    private static List<SocketChannel> listSocketChannel = new ArrayList<>();
    private static ByteBuffer byteBuffer = ByteBuffer.allocate(512);

    public static void main(String[] args) {
        try {
            // 1.创建一个ServerSocketChannel
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            // 2. 绑定地址
            ServerSocketChannel bind = serverSocketChannel.bind(new InetSocketAddress(9090));
            serverSocketChannel.configureBlocking(false);
            while (true) {
                /**channel管道:TCP数据传输的通道*/
                SocketChannel socketChannel = serverSocketChannel.accept();
                if (socketChannel != null) {
                    /**通道加入到选择器中*/
                    socketChannel.configureBlocking(false);
                    listSocketChannel.add(socketChannel);
                }
                /**轮询选择器下的所有通道信息,利用buffer缓存机制读取数据*/
                for (SocketChannel scl : listSocketChannel) {
                    try {
                        int read = scl.read(byteBuffer);
                        if (read > 0) {
                            byteBuffer.flip();
                            Charset charset = Charset.forName("UTF-8");
                            String receiveText = charset.newDecoder().decode
                                    (byteBuffer.asReadOnlyBuffer()).toString();
                            System.out.println(Thread.currentThread().getName()+" receiveText:" + receiveText);
                        }
                        listSocketChannel.remove(scl);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

  ----------------------------
原文链接:https://www.jianshu.com/p/13ef4c5976e8

程序猿的技术大观园:www.javathinker.net



[这个贴子最后由 flybird 在 2021-06-24 10:44:07 重新编辑]
  Java面向对象编程-->对象的生命周期
  JavaWeb开发-->使用过滤器
  JSP与Hibernate开发-->映射组成关系
  Java网络编程-->用Spring整合CXF发布Web服务
  精通Spring-->绑定表单
  Vue3开发-->Vue CLI脚手架工具
  Java内存设置详解(含内存溢出问题的解决)
  java.util.logging.Logger使用详解
  十分钟带你搞懂 Java AQS 核心设计与实现!
  关于新书
  内部类的种类和用法
  java.util.logging.Logger使用详解
  volatile 与 synchronized 详解
  用BigDecimal进行精确运算的范例
  java比c++强大之处JVM垃圾收集算法
  Java入门实用代码:集合输出
  Java入门实用代码:压栈出栈的方法实现字符串反转
  Java 入门实用代码:设置文件只读
  Java判断一个字符是否为中文字符
  java实现PPT转化为PDF
  初学者该学哪种编程语言
  更多...
 IPIP: 已设置保密
树形列表:   
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。