NIO和BIO的比较

NIO:同步非阻塞IO

BIO:同步阻塞IO

AIO:异步非阻塞IO

阻塞:要等到缓冲区中的数据准备好之后,才处理其他事情,否则一直处于等待状态

非阻塞:当我们的进程访问我们的数据缓冲区时,如果数据未准备好,则直接返回,如果数据准备好,也直接返回

(也可理解为阻塞==同步,非阻塞==异步,虽然有些不恰当)

网上大佬对阻塞和非阻塞的解释:

在阻塞模式下,若从网络流中读取不到指定大小的数据量,阻塞IO就在那里阻塞着。比如,已知后面会有10个字节的数据发过来,但是我现在只收到8个字节,那么当前线程就在那傻傻地等到下一个字节的到来,对,就在那等着,啥事也不做,直到把这10个字节读取完,这才将阻塞放开通行。

在非阻塞模式下,若从网络流中读取不到指定大小的数据量,非阻塞IO就立即通行。比如,已知后面会有10个字节的数据发过来,但是我现在只收到8个字节,那么当前线程就读取这8个字节的数据,读完后就立即返回,等另外两个字节再来的时候再去读取。

同步:某个时间段只能做一间事情.(如队列)

异步:某个时间段可以做多个事情(如多线程)

BIO---->阻塞IO(必须等到数据接收完毕才可执行业务逻辑)

           ----->用流传输数据(InputStream/OutputStream)用完即关闭,在用时重新开辟--浪费系统性能

                    ----->发展---线程池

NIO----->同步非阻塞(数据传输和业务分离)

             ---->通过通道(Channel)和缓冲区(buffer)来传输数据,Channel(多路复用机制),避免了BIO流的重复创建和关闭对资源的消耗

                  ------->一个线程轮询(selector选择器),数据准备完成时在去分发线程去处理

 

buffer缓冲区(缓冲区是双向的--->面向缓冲区)----->负责数据的存储

Channel通道(多路复用机制)--->负责链接------>负责数据的传输

selector选择器--->负责监听注册到selector的事件,进行对应的业务处理

缓冲区:负责数据的存取(本质就是数组)-->除了boolean没有缓冲区,其他7种基本数据类型都有缓冲区
        通过allocate()方法获取缓冲区-->可指定大小
        ByteBuffer buf=ByteBuffer.allocate(1024);
        put()-->存入数据到缓冲区
        get()-->从缓冲区中获取数据

四个核心属性
        capacity: 容量,表示缓冲区中最大存储数据的容量,一旦声明不能改变
        limit:界限,表示缓冲区可以操作数据的大小.(limit后的数据不能进行读写)
        position:位置,表示缓冲区中正在操作数据的位置
        0<=mark<=position<=limit<=capacity

        flip()--->切换读模式
        rewind()--->可重复读数据
        clear()--->清空缓冲区
        mark()--->标记,记录当前position的位置,可通过reset()恢复到mark的位置
        hasRemaining()--->判断缓冲区中是否还有剩余的数据
        remaing()--->获取缓冲区中可以操作的数量

直接缓冲区和非直接缓冲区--->通过isDirect()方法可以判断是直接缓冲区,还是非直接缓冲区
        非直接缓冲区:通过allocate()方法分配缓冲区,将缓冲区建立在JVM的内存中
        直接缓冲区:通过allocateDirect()方法分配在操作系统的物理内存中(资源消耗大)

    Channel:用于源节点与目标节点的链接,channel本身不存储数据,需要配合缓冲区进行数据的传输
        主要实现类:
            java.nio.channels.channel
                FileChannel--文件通道
                SocketChannel--
                ServerSocketChannel--套接字通道
                DatagramChannel---UDP通道
    获取通道的三种方法
        1.    本地IO:
            FileInputStream/FileOutputStream
            RandomAccessFile
            网络IO:
            Socket
            ServerSocket
            DatagramSocket
            
        通过getChannel()方法获取通道        
    2.在JDK1.7中的NIO2针对各个通道提供了静态的方法open()也可获取通道
    3.在JDK1.7中的NIO2的Files工具类的newByteChannel()    也可获取通道    

    通道之间的数据传输
        transferTo()--->直接缓冲区
        transferFrom()---->直接缓冲区

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(JAVA技术)