再学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("Hello\nI'm lt\nWh".getBytes());
        split(buffer);
        buffer.put("o are you\n".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<Path>(){
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                System.out.println(file.getFileName());
                return super.visitFile(file, attrs);
            }
        });
    }

发展历程

  1. 接收连接和读取数据是阻塞的
  2. 轮询是否有连接和是否有数据发送,非阻塞,但是一直在轮询
  3. selector出现后,它和channel联系,当有事件发生时才去调用(当事件未处理时,仍会一直调用)处理完key之后要及时移除。如果有耗时长的,影响整体效率。
  4. selector的多线程,一个负责连接事件,一些负责读写事件。

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

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值