NIO常用API

buffer(缓冲区)的常用操作

在Java NIO中负责数据的存取,缓冲区就是数组,用于存储不同类型的缓冲区。为什么说NIO是基于缓冲区的IO方式呢?因为,当一个链接建立完成后,IO的数据未必会马上到达,为了当数据到达时能够正确完成IO操作,在BIO(阻塞IO)中,等待IO的线程必须被阻塞,以全天候地执行IO操作。为了解决这种IO方式低效的问题,引入了缓冲区的概念,当数据到达时,可以预先被写入缓冲区,再由缓冲区交给线程,因此线程无需阻塞地等待IO。

  1. buffer中三个元素
  • limit:界限,表示缓冲区中可以操作数据的大小(limit后数据不能进行读写)
  • capacity:容量,表示缓冲区中最大数据的存储容量
  • position:位置,表示缓冲区中正在操作数据的位置
    2.常用API
  • ByteBuffer bb=ByteBuffer.allocate(1024)
    非直接缓冲区:通过allocate()方法分配缓冲区,将缓冲区建立在JVM的内存中
  • ByteBuffer bb=ByteBuffer.allocateDirect(1024)
    直接缓冲区:通过allocateDirect()方法分配直接缓冲区,将缓冲区建立在物理内存中,可以提高效率
  • bb.put(“test”.getBytes())
    存入数据,写操作,此时capacity=1024,limit=1024,position=4
  • bb.flip()
    读写切换操作,查看源码:
public final Buffer flip() {
        limit = position;
        position = 0;
        mark = -1;
        return this;
    }

可以看出,它是将写的数据的位置(position=4)作为当前的limit,position置为0。所以现在的position=0,limit=4。

  • bb.get()
    byte[] by=new byte[bb.limit()];
    bb.get(by);
    读取数据,将数据读到byte数组,此时读取后,我们的position=limit=4,如果继续全量读取,那么会出现越界。那么怎么可以让数据重复读取呢?
  • bb.rewind()
    是数据可重复读
    我们来看一下他的源码:
  public final Buffer rewind() {
       position = 0;
       mark = -1;
       return this;
   }

很简单,只是将我们的position置为0,这样就可以重复读取了。

  • bb.clear()
    清空缓冲区,但是缓冲区的数据依然存在,我们来看一下源码:
    public final Buffer clear() {
        position = 0;
        limit = capacity;
        mark = -1;
        return this;
    }

可以看出,相当于将所有的变量的值恢复到刚创建的那一刻,limit=capacity,position=0,mark=-1。所以这里的clear可能和我们想象的不一样,此时缓冲区的数据还是存在的。
最后我们再说说mark(),mark通常和reset是一起使用的,

  • mark()
    标记当前所在位置,我们看一下源码。
   public final Buffer mark() {
        mark = position;
        return this;
    }

将position付给mark,这个mark后面会有用。

  • reset()
    重置,我们还是看一下实现:
 public final Buffer reset() {
        int m = mark;
        if (m < 0)
            throw new InvalidMarkException();
        position = m;
        return this;
    }

可以看出,reset必须在mark后使用,不然会报错,因为默认mark=-1,reset主要是将position恢复到我们mark的位置。
最后我们看一下效果

 bb.rewind();
 System.out.println((char)bb.get());
 System.out.println("1:buffer position="+bb.position()+"  limit="+bb.limit());
 System.out.println(bb.mark());
 System.out.println((char)bb.get());
 System.out.println((char)bb.get());
 System.out.println("2:buffer position="+bb.position()+"  limit="+bb.limit());
 bb.reset();
 System.out.println("3:buffer position="+bb.position()+"  limit="+bb.limit());
 System.out.println((char)bb.get());
 System.out.println((char)bb.get());

执行结果:
t
1:buffer position=1 limit=1024
java.nio.HeapByteBuffer[pos=1 lim=1024 cap=1024]
e
s
2:buffer position=3 limit=1024
3:buffer position=1 limit=1024
e
s
可以看出,我们标记–>重置后,会从我们标记的位置开始读取数据。

channel(通道)的常用操作

用于源节点与目标节点的连接,在java NIO 中负责缓冲区中的数据传输,Channel本身不存储数据,因此需要缓冲区配合进行传输,通道就相当于铁轨,缓冲区就相当于火车。
引用 Java NIO 中权威的说法:通道是 I/O 传输发生时通过的入口,而缓冲区是这些数 据传输的来源或目标。对于离开缓冲区的传输,您想传递出去的数据被置于一个缓冲区,被传送到通道。对于传回缓冲区的传输,一个通道将数据放置在您所提供的缓冲区中。
转载于: Java NIO及其常用API

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值