• netty


    nio基础

    nio含义 non-blocking io 非阻塞IO

    三大组件

    channel & buffer

    channel 数据双向通道
    buffer 数据缓冲区

    常见四种channel
    1、FileChannel 文件数据传输通道
    2、DatagramChannel 用于UDP的传输通道
    3、SocketChannel 用于TCP 服务端客户端都可用
    4、ServerSocketChannel 用于TCP 服务端专用

    buffer
    1、ByteBuffer(最常用)
    1.1 MappedByteBuffer
    1.2 DirectByteBuffer
    1.3 HeapByteBuffer
    2、ShortBuffer
    3、IntBuffer
    4、LongBuffer
    5、FloatBuffer
    6、DoubleBuffer
    7、CharBuffer

    Selector

    背景:
    1、多线程是提高效率方法,但是过多的话 CPU跟不上。内存占用高、线程上下文切换成本高、只适合连接数少的场景(一个网络连接看成一个线程)。
    2、使用线程池的话可以通过限制线程数的方法改进1的问题。
    3、但是使用线程池的话,在其阻塞模式下,线程仅能处理一个socket连接,导致线程利用率不高,仅适合短连接场景。

    selector版的设计
    为每个线程提供一个selector,selector监视了多个channel,selecot管理了多个channel,获取这些channel上发生的事件,channel工作在非阻塞模式下(与线程池最大的区别),不会让线程吊死在一个channel上,适合连接数特别多,但流量低的场景。
    事件:可连接、可读、可写

    ByteBuffer

    main(){
    	//输入输出流
    	try(FileChannel channel = new FileInputStream("data.txt").getChannel()){
    		//准备缓冲区
    		ByteBuffer buffer = ByteBuffer.allocate(10);
    		//从channel读取数据,想buffer写入
    		channel.read(buffer);
    		//切换到读模式
    		buffer.flip();
    		while(buffer.hasRemaining()){//是否还有剩余未读数据
    			byte b = buffer.get();//get(i)不会让position往后移,但get()会
    			System.out.println((char) b);
    		}
    	}catch(IOException e){
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    上面代码只能取到10个字符,这里是为了模拟读取多次数据故意这么写的,应为实际场景中allocate的缓冲区不可能分配无限大。
    下面代码为循环使用缓冲

    main(){
    	//输入输出流
    	try(FileChannel channel = new FileInputStream("data.txt").getChannel()){
    		//准备缓冲区
    		ByteBuffer buffer = ByteBuffer.allocate(10);
    		while(true){
    			//从channel读取数据,想buffer写入
    			int len = channel.read(buffer);
    			if(len == -1){//没有内容了
    				break;
    			}
    			//切换到读模式
    			buffer.flip();
    			while(buffer.hasRemaining()){//是否还有剩余未读数据
    				byte b = buffer.get();
    				System.out.println((char) b);
    			}
    			buffer.clear();//切换为写模式
    		}
    	}catch(IOException e){
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    ByteBuffer 结构

    在这里插入图片描述

    属性:
    1、capacity 容量
    2、position 位置(读到那个位置指针)
    3、limit (写入限制,只允许写到哪个位置)
    在这里插入图片描述
    写模式下,向buffer写入数据其中limit等于caoacity
    在这里插入图片描述
    buffer.flip()后 切换为读模式,limit等于写入的最后一个字节的位置可限制只读到有写入数据的位置
    在这里插入图片描述
    clear后切换为写模式
    在这里插入图片描述
    compact方式切换为写模式,用于数据没读完的情况下,保留未读的数据,删除已读数据,且把未读数据往前移
    在这里插入图片描述
    如果没有调用buffer.flip()则从buffer无法读取数据

    使用buffer.compact()切换到写模式会使未读数据前移,建前面已读的位置填满后面的,且写的位置会到前移的上次未读完数据的后一个字节

    ByteBuffer的常见方法

    1、ByteBuffer.allocate(16) java堆内存,读写效率较低,收到垃圾回收的影响
    2、ByteBuffer.allocateDirect(16) 直接内存,读写效率较高(因为会少一次数据拷贝),使用的是系统内存,不会收到垃圾回收的影响。缺点:因为使用的系统内存,所以内存分配比较慢,需要调用操作系统函数

    向buffer写入数据
    int readBytes = channel.read(buf); // 从channel读,向buffer写
    和
    buf.put((byte)127);
    
    • 1
    • 2
    • 3
    从buffer读取数据
    int writeByte = channel.write(buf); //从buffer读,向channel写byte b = buf.get();
    
    • 1
    • 2
    • 3

    get方法会让position读指针向后走,如果想重复读取数据
    可以调用rewind方法将position重新置为0
    或者调用get(int i)方法获取索引 i 的内容,它不会移动读指针

    文件编程

    FileChannel只能工作在阻塞模式下

    获取

    不能直接打开FileChannel,必须通过FileInputStream、FileOutputStream或者RandomAccessFile来获取FileChannel,它们都有getChannel方法。
    通过FileInputStream获取的channel只能读
    通过FileOutputStream获取的channel只能写
    通过RandomAccessFile是否能读写根据构造RandomAccessFile时的读写模式决定

    读取

    在这里插入图片描述

    写入

    在这里插入图片描述

    关闭

    在这里插入图片描述

    位置

    在这里插入图片描述

    两个Channel传输数据

    重要
    transferTo函数:将from内容传到to里面
    这个函数效率高,底层会利用操作系统的零拷贝进行优化
    在这里插入图片描述

  • 相关阅读:
    javascript异步编程之generator(生成器函数)与asnyc/await语法糖
    【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
    走进Elasticsearch
    sql题目练习
    Java 中 Cloneable 接口和 clone() 方法的使用
    Python编程 print输出函数
    Cadence Allegro PCB设计88问解析(十五) 之 Allegro中如何替换过孔类型
    【MySQL】-增删查改
    Java+SpringBoot+Vue+MySQL:农业管理新篇章
    MAX30102驱动
  • 原文地址:https://blog.csdn.net/qq_39103818/article/details/126003687