IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 第一次见有人能把BIO,NIO说得这么清楚 -> 正文阅读

[数据结构与算法]第一次见有人能把BIO,NIO说得这么清楚

下面的只是对知识点的高度抽象,有些细节会有出入

BIO,NIO可以与Selector随意组合:BIO,NIO,BIO+Selector,NIO+Selector

-selector+selector
BIOBIOBIO+Selector
NIONIONIO+Selector

IO模型使用不使用Selector区别在于:系统调用来获取有事件的channel的次数的不同

单独BIO,NIO因为要对IO进行访问,必然要系统调用,在用户层级就是可以维护一个List,每次有channel就往里面添加 ,之后不断遍历所有的channel来处理连接与读写请求等,这样每一次遍历每个通道获取事件都会去有次系统调用
组合BIO+Selector,NIO+Selector ,其中selector的作用就是通过一次系统调用去获取有事件的channel,这个功能是内核实现的,而不是像单独的版本是要多次系统调用,当然在组合的返回的有事件的还是需要你去一个个使用系统调用

总的来说:用了selector你就能使用一次系统调用获取有事件的channel,没有使用selector需要在用户层面多次使用系统调用获取有事件的channel

另外selector的poll与epoll模型区别最大在于:在内核模式下是否要对所有的channel全量的扫描。当然还有文件描述符的复制的不同

poll使用一次系统调用,在内核下会对每个channel进行扫描;epoll基于中断会把有事件的channel注册到一个空间去,一次系统调用直接就能拿到有事件的channel,不同poll需要扫描。
epoll的实现就是基于中断(增加补偿逻辑),红黑树(用于注册),链表(存放有事件的channel)实现,具体就不说了

下面这个代码只是演示我上面的思想

public class NIO{

    public static void main(String[] args) throws Exception {

        List<Channel> clients = new LinkedList<>();
        ServerSocketChannel ss = ServerSocketChannel.open();
        ss.bind(new InetSocketAddress(9090));
        ss.configureBlocking(false); //BIO即注释掉这一行
        clients.add(ss);

        while (true) {
           //遍历通道
            for (Channel c : clients) {
                //处理连接
                if(c instanceof ServerSocketChannel){
                    SocketChannel client = ss.accept();
                    if (client != null) {
                        System.out.println("处理连接");
                        client.configureBlocking(false); //BIO即注释掉这一行
                        clients.add(client);
                    }
                }
                //处理读写
                ByteBuffer buffer = ByteBuffer.allocateDirect(4096);
                if(c instanceof  SocketChannel){
                    int num =  ((SocketChannel) c).read(buffer);
                    if (num > 0) {
                        buffer.flip();
                        byte[] aaa = new byte[buffer.limit()];
                        buffer.get(aaa);
                        System.out.println("处理读:"+ new String(aaa));
                        buffer.clear();
                    }
                }

            }
        }
    }

}
public class NIO_Selector{

   
    private ServerSocketChannel server = null;
    private Selector selector = null;  
    int port = 9090;

    public void initServer() {
        try {
          
            server = ServerSocketChannel.open();
            server.bind(new InetSocketAddress(port));
            server.configureBlocking(false);    //BIO+Selector即注释掉这一行
            selector = Selector.open();
            server.register(selector, SelectionKey.OP_ACCEPT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void start() {
        initServer();
        System.out.println("服务器启动了....");
        try {
            while (true) {  //死循环
                Set<SelectionKey> keys = selector.keys();
                System.out.println(keys.size()+"   size");

            
                while (selector.select() > 0) { //返回的有状态的fd集合
                    Set<SelectionKey> selectionKeys = selector.selectedKeys(); 
                    Iterator<SelectionKey> iter = selectionKeys.iterator();
                    while (iter.hasNext()) {
                        SelectionKey key = iter.next();
                        iter.remove();
                        if (key.isAcceptable()) {                 
                            ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
                            SocketChannel client = ssc.accept(); 
                            client.configureBlocking(false); //BIO+Selector即注释掉这一行
                            ByteBuffer buffer = ByteBuffer.allocate(8192);  
                            client.register(selector, SelectionKey.OP_READ, buffer);
                        } else if (key.isReadable()) {
                            readHandler(key);
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        com.bjmashibing.system.io.SocketMultiplexingSingleThreadv1 service = new com.bjmashibing.system.io.SocketMultiplexingSingleThreadv1();
        service.start();
    }
}



  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-05 17:36:08  更:2021-08-05 17:37:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 18:47:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码