浅谈NIO(一)

NIO描述

什么是NIO?

NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。

传统的IO包提供的是同步阻塞IO而Java NIO可以让你非阻塞的使用IO,例如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情。当数据被读取到缓冲区时,线程可以继续处理它。从缓冲区写入通道也类似。数据由缓冲区进行交互。非阻塞的核心就是通道和缓冲区,当 IO 事件就绪时,可以通过写道缓冲区,保证 IO 的成功,而无需线程阻塞式地等待。

Java NIO: Selectors(选择器)

Java NIO引入了选择器的概念,选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。

 

NIO和IO的主要区别

IO

NIO

面向流

面向缓冲区

阻塞IO

非阻塞IO

选择器

 

API用法

/**
 * Buffer类的子类
 * ByteBuffer(用的最多)
 * CharBuffer
 * ShortBuffer
 * IntBuffer
 * LongBuffer
 * FloatBuffer
 * DoubleBuffer
 * 没有 BooleanBuffer
 *
 * Buffer类中四个比较重要的参数:
 *  mark = -1; 标记
 *  position 缓冲区正在操作的位置,默认从0开始
 *  limit    缓冲区可用大小,默认1024,缓冲创建时,limit 的值等于 capacity 的值,
 *      假设我们创建的时候给limit设值为100,那么缓冲区容量是1024,但是实际可用容量是100
 *  capacity 缓冲区最大容量,这一容量在缓冲区创建时被设定,并且永远不能被改变。
 *
 *  子类中两个比较重要的方法(父类并没有这两个方法)
 *  put:往buffer中存放数据
 *  get:获取数据
 */
public class NioDemo {
    public static void main(String[] args) {
        //初始化ByteBuffer大小,调用这个方法产生的是非直接缓冲区,效率慢但是安全
        ByteBuffer allocate = ByteBuffer.allocate(1024);
        System.out.println(allocate.position());//0
        System.out.println(allocate.limit());//1024
        System.out.println(allocate.capacity());//1024

        System.out.println("---------放入数据----------");

        //放入数据
        allocate.put("abc".getBytes());
        System.out.println(allocate.position());//3
        //limit表示整个Buffer可用的大小,就算之前用过大小还是不变
        System.out.println(allocate.limit());//1024
        System.out.println(allocate.capacity());//1024

        System.out.println("--------读取值-----------");

        /**
         * 如果要读取值,必须得开启读取模式不然会报错,
         * java.nio.BufferUnderflowException
         * 因为之前position已经从3开始了,所以这里是读不到的,需要
         * 把position重置为0
         * System.out.println(allocate.position());//3
         * System.out.println(allocate.limit());//1024
         * System.out.println(allocate.capacity());//1024
         * byte[] bytes = new byte[allocate.limit()];
         * allocate.get(bytes);
         * System.out.println(new String(bytes,0,bytes.length));
         */
        //当读取值的时候,limit的值会和读取的值的长度一样
        allocate.flip();
        System.out.println(allocate.position());//0
        System.out.println(allocate.limit());//3
        System.out.println(allocate.capacity());//1024
        byte[] bytes = new byte[allocate.limit()];
        allocate.get(bytes);
        System.out.println(new String(bytes,0,bytes.length));//abc
//        allocate.get(bytes);
//        System.out.println(new String(bytes,0,2));//ab

        /**
         * 当上面第一次读完的时候position已经变成了3,所以第二次读取的时候,
         * 如果不把position重置为0,还是会报错,需要添加一个方法
         * allocate.rewind()
         */

        System.out.println("--------清空缓存区-----------");

        //当清空缓存的时候,只是把界限变成了一开始的状态,但是值还是存在,
        //数据被遗忘
        allocate.clear();
        System.out.println(allocate.position());//0
        System.out.println(allocate.limit());//1024
        System.out.println(allocate.capacity());//1024
        System.out.println((char)allocate.get());// a
    }

}

 

posted @ 2018-08-14 13:24  奥克兰毛泽西  阅读(115)  评论(0编辑  收藏  举报