Java NIO原理及实例

部分转载自: Java NIO原理及实例
部分转载自: Java NIO

Java IO的各种流是阻塞的。这意味着当一个线程调用read()和write()时,该线程被阻塞,知道数据被读出或者数据完全写入。
Java NIO的非阻塞模式,是一个线程从某通道发送请求读取数据,但是只可以读取到目前有的数据,如无数据则什么都不会获取。而不是保持线程阻塞。一个线程请求写入一些数据到某通道,但不需要等待它完全写入。

通道

类似于流,但是可以异步读写数据,且通道可以是双向的。通道的数据总是先读到一个buffer或者从一个buffer写入,即通道与buffer进行数据交互。
通道类型:
① FileChannel: 从文件中读取数据,不能切换到非阻塞模式(特殊)
② DatagramChannel: 能通过UDP读取网络中的数据
③ SocketChannel: 能通过TCP读取网络中的数据
④ ServerSocketChannel: 可以监听新进来的TCP连接。对每一个新进来的连接都会创建一
个SocketChannel

缓存区Buffer
属性:
capacity: 缓存区的容量,一旦设定不可更改
position: 初始值为0,读或写时,每一步加1
limit: 写模式下,limit代表着最大写入的数据量,此时limit=capacity。读模式下,limit=buffer中实
际数据大小
方法:
allocate(); 分配一块缓存区 ByteBuffer.allocate(1024)
put(); 向缓存区写数据

    final byte[] hb;  
    public ByteBuffer put(byte x) {
        hb[ix(nextPutIndex())] = x;
        return this;
    }
    final int nextPutIndex() {                          // package-private
        if (position >= limit)
            throw new BufferOverflowException();
        return position++;
    }

get(); 从缓存区读数据

    public byte get() {
        return hb[ix(nextGetIndex())];
    }
    final int nextGetIndex() {                          // package-private
        if (position >= limit)
            throw new BufferUnderflowException();
        return position++;
    }

flip(); 将缓存区从写模式切换到读模式,position置为0

    public final Buffer flip() {
        limit = position;
        position = 0;
        mark = -1;
        return this;
    }

clear(); 从读模式切换为写模式,不会清空数据,但后续写操作会覆盖已有数据

    public final Buffer clear() {
        position = 0;
        limit = capacity;
        mark = -1;
        return this;
    }

compact(); 从读模式切换为写模式,未读数据会被复制到缓存区头部,后续写操作在已有数据后
新增

    public ByteBuffer compact() {
        System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
        position(remaining());
        limit(capacity());
        discardMark();
        return this;
    }

mark(); 对position做出标记,配合reset使用

    public final Buffer mark() {
        mark = position;
        return this;
    }

reset(); 将position置为标记值

    public final Buffer reset() {
        int m = mark;
        if (m < 0)
            throw new InvalidMarkException();
        position = m;
        return this;
    }

选择器(多路复用)

相当于一个观察者,用来监听通道感兴趣的事件,一个选择器可以绑定多个通道;用于实现非阻
塞IO

通道向选择器注册时,需要指定感兴趣的事件,选择器支持以下事件:

① SelectionKey.OP_CONNECT 成功建立TCP连接
② SelectionKey.OP_ACCEPT 接受TCP连接
③ SelectionKey.OP_READ
④ SelectionKey.OP_WRITE

// 开启一个Selector
Selector selector = Selector.open();
SocketChannel channel = SocketChannel.open();
// 将通道设为非阻塞模式,默认阻塞
channel.configureBlocking(false);
// 注册
SelectionKey key =
channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);

你可能感兴趣的:(IO)