首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Java NIO原理跟使用

2012-07-01 
Java NIO原理和使用?原来的?I/O?以流的方式处理数据,而?NIO?以块的方式处理数据。?面向流?的?I/O?系统一次

Java NIO原理和使用

?

原来的?I/O?以流的方式处理数据,而?NIO?以块的方式处理数据。?面向流?的?I/O?系统一次一个字节地处
Java NIO原理跟使用理数据。一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。为流式数据创建过滤器非常容易。链接几个过滤器,以便每个过滤器只负责单个复杂处理机制的一部分,这样也是相对简单的。不利的一面是,面向流的?I/O?通常相当慢。?一个?面向块?的?I/O?系统以块的形式处理数据。每一个操作都在一步中产生或者消费一个数据块。按块处理数据比按(流式的)字节处理数据要快得多。但是面向块的?I/O?缺少一些面向流的I/O?所具有的优雅性和简单性。?


?本文主要简单介绍NIO的基本原理,在下一篇文章中,将结合Reactor模式和著名线程大师Doug Lea的一篇文章深入讨论。

NIO主要原理和适用。

NIO 有一个主要的类Selector,这个类似一个观察者,只要我们把需要探知的socketchannel告诉Selector,我们接着做别的事情,当有事件发生时,他会通知我们,传回一组SelectionKey,我们读取这些Key,就会获得我们刚刚注册过的socketchannel,然后,我们从这个Channel中读取数据,放心,包准能够读到,接着我们可以处理这些数据。

Selector内部原理实际是在做一个对所注册的channel的轮询访问,不断的轮询(目前就这一个算法),一旦轮询到一个channel有所注册的事情发生,比如数据来了,他就会站起来报告,交出一把钥匙,让我们通过这把钥匙来读取这个channel的内容。

首先简单的印象是NIO快,所以想写个程序验证一下.如下复制:

Java NIO原理跟使用??public???static???void??test2(String?name1,?String?name2)???{
Java NIO原理跟使用?????????long??start??=??System.currentTimeMillis();
Java NIO原理跟使用??????????try????{
Java NIO原理跟使用????????????FileInputStream?fis??=???new??FileInputStream(name1);
Java NIO原理跟使用????????????FileOutputStream?fos??=???new??FileOutputStream(name2);
Java NIO原理跟使用?????????????byte?[]?buf??=???new???byte?[?8129?];
Java NIO原理跟使用??????????????while??(?true?)???{????????????????
Java NIO原理跟使用?????????????????int??n??=??fis.read(buf);
Java NIO原理跟使用??????????????????if??(n??==???-?1?)???{
Java NIO原理跟使用??????????????????????break?;
Java NIO原理跟使用?????????????????}?
Java NIO原理跟使用?????????????????fos.write(buf,?0?,n);
Java NIO原理跟使用?????????????}?
Java NIO原理跟使用?????????????fis.close();
Java NIO原理跟使用????????????fos.close();
Java NIO原理跟使用??????????}???catch??(Exception?e)???{
Java NIO原理跟使用????????????e.printStackTrace();
Java NIO原理跟使用????????}?
Java NIO原理跟使用?????????long??end??=??System.currentTimeMillis();
Java NIO原理跟使用??????????long??time??=??end??-??start;
Java NIO原理跟使用????????System.out.println(time);
Java NIO原理跟使用?????}?
Java NIO原理跟使用????
Java NIO原理跟使用???????public???static???void??test3(String?name1,?String?name2)???{
Java NIO原理跟使用?????????long??start??=??System.currentTimeMillis();
Java NIO原理跟使用???????????try????{
Java NIO原理跟使用?????????????FileInputStream?in??=???new??FileInputStream(name1);
Java NIO原理跟使用?????????????FileOutputStream?out??=???new??FileOutputStream(name2);
Java NIO原理跟使用????????????FileChannel?fc1??=??in.getChannel();
Java NIO原理跟使用????????????FileChannel?fc2??=??out.getChannel();
Java NIO原理跟使用????????????ByteBuffer?bb??=??ByteBuffer.allocate(?8129?);
Java NIO原理跟使用???????????????while??(?true?)???{
Java NIO原理跟使用?????????????????bb.clear();
Java NIO原理跟使用?????????????????int??n??=??fc1.read(bb);
Java NIO原理跟使用???????????????????if??(n??==???-?1?)???{
Java NIO原理跟使用??????????????????????break?;
Java NIO原理跟使用????????????????}?
Java NIO原理跟使用?????????????????bb.flip();
Java NIO原理跟使用?????????????????fc2.write(bb);
Java NIO原理跟使用?????????????}?
Java NIO原理跟使用?????????????fc1.close();
Java NIO原理跟使用????????????fc2.close();
Java NIO原理跟使用??????????}???catch??(IOException?e)???{
Java NIO原理跟使用??
Java NIO原理跟使用????????}?
Java NIO原理跟使用??????????long??end??=??System.currentTimeMillis();
Java NIO原理跟使用??????????long??time??=??end??-??start;
Java NIO原理跟使用?????????System.out.println(time);
Java NIO原理跟使用?????}?

本以为可以结束,结果测试结果出乎意料,函数一比函数二要快,就是说Old IO快于NIO ,从此也就开始了整个过程:


?为了了解这个问题,仔细搜索并仔细再看IBM 的NIO教程,看到如下这段话
?---------------------------------------------
?在 JDK 1.4 中原来的 I/O 包和 NIO 已经很好地集成了。 java.io.* 已经以 NIO 为基础重新实现了,
?所以现在它可以利用 NIO 的一些特性。例如, java.io.* 包中的一些类包含以块的形式读写数据的方法,
?这使得即使在更面向流的系统中,处理速度也会更快。 也可以用 NIO 库实现标准 I/O 功能。例如,
?可以容易地使用块 I/O 一次一个字节地移动数据。但是正如您会看到的,NIO 还提供了原 I/O 包中所没有的许多好处。?
??? ---------------------------------------------

了解了这个基本原理,我们结合代码看看使用,在使用上,也在分两个方向,一个是线程处理,一个是用非线程,后者比较简单,看下面代码:

Java NIO原理跟使用import?java.io.*;
Java NIO原理跟使用import?java.nio.*;
Java NIO原理跟使用import?java.nio.channels.*;
Java NIO原理跟使用import?java.nio.channels.spi.*;
Java NIO原理跟使用import?java.net.*;
Java NIO原理跟使用import?java.util.*;?
Java NIO原理跟使用/**
Java NIO原理跟使用*
Java NIO原理跟使用*?@author?Administrator
Java NIO原理跟使用*?@version
Java NIO原理跟使用*/
Java NIO原理跟使用public?class?NBTest?{
Java NIO原理跟使用
Java NIO原理跟使用
Java NIO原理跟使用  /**?Creates?new?NBTest?*/
Java NIO原理跟使用  public?NBTest()
Java NIO原理跟使用  {
Java NIO原理跟使用  }
Java NIO原理跟使用
Java NIO原理跟使用  public?void?startServer()?throws?Exception
Java NIO原理跟使用  {
Java NIO原理跟使用  int?channels?=?0;
Java NIO原理跟使用  int?nKeys?=?0;
Java NIO原理跟使用  int?currentSelector?=?0;
Java NIO原理跟使用
Java NIO原理跟使用  //使用Selector
Java NIO原理跟使用  Selector?selector?=?Selector.open();
Java NIO原理跟使用
Java NIO原理跟使用  //建立Channel?并绑定到9000端口
Java NIO原理跟使用  ServerSocketChannel?ssc?=?ServerSocketChannel.open();
Java NIO原理跟使用  InetSocketAddress?address?=?new?InetSocketAddress(InetAddress.getLocalHost(),9000);?
Java NIO原理跟使用  ssc.socket().bind(address);
Java NIO原理跟使用
Java NIO原理跟使用  //使设定non-blocking的方式。
Java NIO原理跟使用  ssc.configureBlocking(false);
Java NIO原理跟使用
Java NIO原理跟使用  //向Selector注册Channel及我们有兴趣的事件
Java NIO原理跟使用  SelectionKey?s?=?ssc.register(selector,?SelectionKey.OP_ACCEPT);
Java NIO原理跟使用  printKeyInfo(s);
Java NIO原理跟使用
Java NIO原理跟使用  while(true)?//不断的轮询
Java NIO原理跟使用  {
Java NIO原理跟使用    debug("NBTest:?Starting?select");
Java NIO原理跟使用
Java NIO原理跟使用    //Selector通过select方法通知我们我们感兴趣的事件发生了。
Java NIO原理跟使用    nKeys?=?selector.select();
Java NIO原理跟使用    //如果有我们注册的事情发生了,它的传回值就会大于0
Java NIO原理跟使用    if(nKeys?>?0)
Java NIO原理跟使用    {
Java NIO原理跟使用      debug("NBTest:?Number?of?keys?after?select?operation:?"?+nKeys);
Java NIO原理跟使用
Java NIO原理跟使用      //Selector传回一组SelectionKeys
Java NIO原理跟使用      //我们从这些key中的channel()方法中取得我们刚刚注册的channel。
Java NIO原理跟使用      Set?selectedKeys?=?selector.selectedKeys();
Java NIO原理跟使用      Iterator?i?=?selectedKeys.iterator();
Java NIO原理跟使用      while(i.hasNext())
Java NIO原理跟使用      {
Java NIO原理跟使用      ? ?s?=?(SelectionKey)?i.next();
Java NIO原理跟使用      ? ?printKeyInfo(s);
Java NIO原理跟使用      ? ?debug("NBTest:?Nr?Keys?in?selector:?"?+selector.keys().size());
Java NIO原理跟使用
Java NIO原理跟使用      ? ?//一个key被处理完成后,就都被从就绪关键字(ready?keys)列表中除去
Java NIO原理跟使用      ? ?i.remove();
Java NIO原理跟使用      ? ?if(s.isAcceptable())
Java NIO原理跟使用      ? ?{
Java NIO原理跟使用      ? ? ?//?从channel()中取得我们刚刚注册的channel。
Java NIO原理跟使用      ? ? ?Socket?socket?=?((ServerSocketChannel)s.channel()).accept().socket();
Java NIO原理跟使用      ? ? ?SocketChannel?sc?=?socket.getChannel();
Java NIO原理跟使用
Java NIO原理跟使用      ? ? ?sc.configureBlocking(false);
Java NIO原理跟使用      ? ? ?sc.register(selector,?SelectionKey.OP_READ?|SelectionKey.OP_WRITE);
Java NIO原理跟使用      ? ? ?      ? ? ?System.out.println(++channels);
Java NIO原理跟使用      ? ?}
Java NIO原理跟使用      ? ?else
Java NIO原理跟使用      ? ?{
Java NIO原理跟使用      ? ? ?debug("NBTest:?Channel?not?acceptable");
Java NIO原理跟使用      ? ?}
Java NIO原理跟使用     ?}
Java NIO原理跟使用   }
Java NIO原理跟使用   else
Java NIO原理跟使用   {
Java NIO原理跟使用      debug("NBTest:?Select?finished?without?any?keys.");
Java NIO原理跟使用   }
Java NIO原理跟使用
Java NIO原理跟使用 ?}
Java NIO原理跟使用
Java NIO原理跟使用}
Java NIO原理跟使用
Java NIO原理跟使用
Java NIO原理跟使用private?static?void?debug(String?s)
Java NIO原理跟使用{
Java NIO原理跟使用 ?System.out.println(s);
Java NIO原理跟使用}
Java NIO原理跟使用
Java NIO原理跟使用
Java NIO原理跟使用private?static?void?printKeyInfo(SelectionKey?sk)
Java NIO原理跟使用{
Java NIO原理跟使用 ?String?s?=?new?String();
Java NIO原理跟使用
Java NIO原理跟使用 ?s?=?"Att:?"?+?(sk.attachment()?==?null???"no"?:?"yes");
Java NIO原理跟使用 ?s?+=?",?Read:?"?+?sk.isReadable();
Java NIO原理跟使用 ?s?+=?",?Acpt:?"?+?sk.isAcceptable();
Java NIO原理跟使用 ?s?+=?",?Cnct:?"?+?sk.isConnectable();
Java NIO原理跟使用 ?s?+=?",?Wrt:?"?+?sk.isWritable();
Java NIO原理跟使用 ?s?+=?",?Valid:?"?+?sk.isValid();
Java NIO原理跟使用 ?s?+=?",?Ops:?"?+?sk.interestOps();
Java NIO原理跟使用 ?debug(s);
Java NIO原理跟使用}
Java NIO原理跟使用
Java NIO原理跟使用
Java NIO原理跟使用/**
Java NIO原理跟使用*?@param?args?the?command?line?arguments
Java NIO原理跟使用*/
Java NIO原理跟使用public?static?void?main?(String?args[])
Java NIO原理跟使用{
Java NIO原理跟使用 ?NBTest?nbTest?=?new?NBTest();
Java NIO原理跟使用 ?try
Java NIO原理跟使用 ?{
Java NIO原理跟使用 ? ?nbTest.startServer();
Java NIO原理跟使用 ?}
Java NIO原理跟使用 ? ?catch(Exception?e)
Java NIO原理跟使用 ?{
Java NIO原理跟使用 ? ?e.printStackTrace();
Java NIO原理跟使用 ?}
Java NIO原理跟使用}
Java NIO原理跟使用
Java NIO原理跟使用}
Java NIO原理跟使用
Java NIO原理跟使用
Java NIO原理跟使用
Java NIO原理跟使用


这是一个守候在端口9000的noblock server例子,如果我们编制一个客户端程序,就可以对它进行互动操作,或者使用telnet 主机名 90000 可以链接上。

通过仔细阅读这个例程,相信你已经大致了解NIO的原理和使用方法,下一篇,我们将使用多线程来处理这些数据,再搭建一个自己的Reactor模式。

热点排行