JAVA NIO 基础(一)

来源:互联网 发布:机油加盟代理淘宝 编辑:程序博客网 时间:2024/06/15 13:37

NIO很少公司在用,大多是在用neety了,感觉已经被遗弃了,这段时间,整理一下NIO相关方面的知识,结合自己做的小游戏,用它来介绍NIO如何使用,会介绍基础原理,主要以实例为主。

IO简单介绍:

IO,简单的说,就是把数据移进或移出缓冲区。JVMA进程执行IO操作,要求缓区被填满,就会间接调用系统命令read(),内核会向磁盘控制器发出命令,请求读取磁盘据,这一步由DMA完成。当磁盘控制器将缓冲区填满时,内核会把数据从内核缓冲区拷贝到IO进程,执行read调用时指定的缓冲区.如下图:


用户空间:常规进程所在的区域。JVM就在用户空间,在该区域执行的代码不能直接访问硬件设备。

内核空间:操作系统所在的区域。能与设备管理器通讯,控制用户进程的运行状态等。

NIO提供的新抽象:

ByteBuffer:字节缓冲区

属性介绍:

容量(Capacity)::缓冲区能够容纳的数据元素的最大数量。这一容量在缓冲区创建时被设定,并且永远不能被改变。
上限(Limit):缓冲区中现存元素的计数。通道会从position位置开始获取,取到limit位置结束.
位置(Position):元素索引。位置会自动由相应的get()和put()方法更新。
标记( MarK ) :一个备忘位置。

这四个属性遵循以下关系:

0 <= mark <= position <= limit <= capacity

例子:

ByteBuffer bb = ByteBuffer.allocate(Short.SIZE / 8 + Integer.SIZE / 8);System.out.println("填充前:");System.out.println("capatity:" + bb.capacity());System.out.println("position:" + bb.position());System.out.println("limit:" + bb.limit());bb.putShort((short) 1);bb.putInt(2);System.out.println("填充后:");System.out.println("capatity:" + bb.capacity());System.out.println("position:" + bb.position());System.out.println("limit:" + bb.limit());/*** * 填充前: *  capatity:6  *  position:0  *  limit:6  *   *  填充后: *   capatity:6 *   position:6  *   limit:6 */


方法介绍:

put()/get():存取。

        flip():翻转

compact():压缩

   下面是代码模拟:

ByteBuffer bb = ByteBuffer.allocate(Short.SIZE / 8 + Integer.SIZE / 8);System.out.println("填充前:");System.out.println("capatity:" + bb.capacity());System.out.println("position:" + bb.position());System.out.println("limit:" + bb.limit());bb.putShort((short) 1);bb.putInt(2);System.out.println("填充后:");System.out.println("capatity:" + bb.capacity());System.out.println("position:" + bb.position());System.out.println("limit:" + bb.limit());// 将位置值重新设为0,通道就会从正确位置开始获取bb.flip();System.out.println("翻转后:");System.out.println("capatity:" + bb.capacity());System.out.println("position:" + bb.position());System.out.println("limit:" + bb.limit());/*** * 填充前: capatity:6 position:0 limit:6 填充后: capatity:6 position:6 limit:6 * 翻转后: capatity:6 position:0 limit:6 */bb.getShort();System.out.println("get后:");System.out.println("capatity:" + bb.capacity());System.out.println("position:" + bb.position());System.out.println("limit:" + bb.limit());// 有时,您可能只想从缓冲区中释放一部分数据,而不是全部,然后重新填充bb.compact();System.out.println("compact后:");System.out.println("capatity:" + bb.capacity());System.out.println("position:" + bb.position());<p>System.out.println("limit:" + bb.limit());</p>/*** * 填充前: capatity:6 position:0 limit:6 * 填充后: capatity:6 position:6 limit:6 * 翻转后: capatity:6 position:0 limit:6 * get后: capatity:6 position:2  limit:6  * compact后: capatity:6 position:4 limit:6 */

Chnnel:通道

通道是双向的,可以读也可以写。常用的有SokcetChannel,ServerSocketChannel.

ServerSocketChannel:是一个基于通道的socket监听器.ServerSocketChannel没有bind( )方法,可以通过调用socket()方法来获取ServerSocket对象,用这个对象去绑定地址,然后ServerSocketChannel调用accept()方法等待连接。

SocketChannel:扮演客户端向服务器发起连接。open()方法会创建一个SocketChannel对象,调用connect()来将该socket通道连接。

Selector:选择器

选择器管理着被注册通道集合的信息和他们就绪的状态。通道是和选择器一起被注册的,并且使用选择器来更新通道的就绪状态.选择器用来管理通道。

SelectionKey:选择键

选择键封装了特定的通道与特定的选择器的注册关系.通道会调用register方法去注册选择器,并注册相应的选择键。通道和选择器的关系封装在选择键里.


这一篇就讲到这里,下 一篇将用到这些知识。

0 0
原创粉丝点击