>>分享Java编程技术,对《Java面向对象编程》等书籍提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 14382 个阅读者 刷新本主题
 * 贴子主题:  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中使用JavaBean(Ⅱ)
  JSP与Hibernate开发-->映射一对多关联关系
  Java网络编程-->Java反射机制
  精通Spring-->Vue组件开发高级技术
  Vue3开发-->创建综合购物网站应用
  10道Java编程基础练习题
  Java虚拟机进行类连接的原理
  快速理解 函数式编程,响应式编程,链式编程
  JAVA锁相关知识总结
  面向对象的七大原则,你知道几个?
  18 张图弄懂面试官必问的一致性哈希
  Redis安装、Redis基本数据类型、Jedis、Redis集群搭建
  JDBC API中的桥接模式
  java.util.logging.Logger使用详解
  Java设计模式:抽象工厂模式
  正则表达式:运算符优先级
  Java设计模式:观察者模式
  正则表达式性能调优
  Java 入门实用代码:设置文件只读
  Java入门实用代码:向文件写入字符串
  更多...
 IPIP: 已设置保密
楼主      
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


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