栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

再学IO模型到Netty笔记(回顾一)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

再学IO模型到Netty笔记(回顾一)

NIO三大核心组件

Selector:之前没有Selector时,多线程时一个客户端对应一个线程会造成上下文切换频繁,占用CPU资源,内存占用高,适合连接数较少。使用线程池时,仅适用短链接场景,阻塞模式下只能处理一个连接。有了Selector之后,一个线程对应一个Selector对应多个连接。Selector监控事件的发生,交给线程处理。是非阻塞的。适用于连接数多,但是流量不高的情况。

Buffer:可以从Channel读数据,也可以向Channel写数据,用来缓冲读写数据,外部数据一定是先经过Buffer

Channel:类似于Stream,但他是双向的。可以从Buffer读数据,也可以向Buffer写数据,常见的Channel有

FileChannel;
DatagramChannel; //UDP
SocketChannel;
ServerSocketChannel;
ByteBuffer

读写案例

从IO模型到Netty笔记(一)_明天一定.的博客-CSDN博客IO模型,NIO三大核心https://blog.csdn.net/wai_58934/article/details/123145720

 注意

使用时要注意读写切换

buffer.flip(); //切换读
buffer.clear(); //切换写
buffer.rewind(); //反复读取时,从头读
buffer.get(); //一次拿一个字节

模拟解决黏包问题

public class Get {
    public static void main(String[] args) {
        ByteBuffer buffer = ByteBuffer.allocate(32);
        buffer.put("HellonI'm ltnWh".getBytes());
        split(buffer);
        buffer.put("o are youn".getBytes());
        split(buffer);
    }

    private static void split(ByteBuffer buffer) {
        buffer.flip();
        for (int i = 0; i < buffer.limit(); i++) {
            if(buffer.get(i)=='n'){
                int len = i-buffer.position()+1;
                ByteBuffer allocate = ByteBuffer.allocate(len);
                for (int j = 0; j < len; j++) {
                    allocate.put(buffer.get());
                }
                System.out.print(new String(allocate.array()));
            }
        }
        buffer.compact();
    }
}

 byteBuffer涉及到分包的问题,自己处理比较麻烦,建议使用netty封装好的类

NIO遍历文件夹

简单案例,根据业务重写SimpleFileVisitor的方法即可。

    public static void main(String[] args) throws IOException {
        Files.walkFileTree(Paths.get("D:\xxxxxxxxxxxxxxxxxxx"), new SimpleFileVisitor(){
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                System.out.println(file.getFileName());
                return super.visitFile(file, attrs);
            }
        });
    }
发展历程
    接收连接和读取数据是阻塞的轮询是否有连接和是否有数据发送,非阻塞,但是一直在轮询selector出现后,它和channel联系,当有事件发生时才去调用(当事件未处理时,仍会一直调用)处理完key之后要及时移除。如果有耗时长的,影响整体效率。selector的多线程,一个负责连接事件,一些负责读写事件。

处理断开异常可以捕获异常并使用key.cancle()取消事件。

处理正常断开可以判断channel.read(buffer)返回值是否为-1,然后再取消。

每个channel可以注册一个附件,并用key.attachment()拿到。

两线程确定执行顺序解决方案之一是使用线程安全的队列,先把线程放入队列,等待该执行时机取出并执行。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/778458.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号