java NIO

Java NIO提供了与标准IO不同的IO工作方式:

    • Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。
    • Asynchronous IO(异步IO):Java NIO可以让你异步的使用IO,例如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情。当数据被写入到缓冲区时,线程可以继续处理它。从缓冲区写入通道也类似。
    • Selectors(选择器):Java NIO引入了选择器的概念,选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。

1. Channel的实现

Java NIO中最重要的通道的实现:

    • FileChannel:从文件中读写数据。
    • DatagramChannel:能通过UDP读写网络中的数据。
    • SocketChannel:能通过TCP读写网络中的数据。
    • ServerSocketChannel:可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。

2. Buffer的类型

Java NIO 有以下Buffer类型:

    • ByteBuffer
    • MappedByteBuffer
    • CharBuffer
    • DoubleBuffer
    • FloatBuffer
    • IntBuffer
    • LongBuffer
    • ShortBuffer

2. Selector(选择器)

  Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件。这样,一个单独的线程可以管理多个channel,从而管理多个网络连接。
Selector监听Channel时间类型:

  • SelectionKey.OP_CONNECT    connect事件   socketChannel 通过连接事件连接
  • SelectionKey.OP_ACCEPT       accept 事件    serverSocketChannel 通过accept方法接收SocketChannel
  • SelectionKey.OP_READ          Read 事件       Channel通过read方法将数据写到buffer中 
  • SelectionKey.OP_WRITE         Write 事件      Channel通过write方法将buffer中的数据写到通道中

eg:

  监听端口888得到的数据

  ServerSocketChannel  serverSocketChannel1 = ServerSocketChannel.open();

  serverSocketChannel1.socket().bind(new InetSocketAddress(888));  // 监听888端口 

  SocketChannel channel =  serverSocketChannel.accept();   

  SocketChannel socketChannel = SocketChannel.open();   

  socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80));  

  Selector selector = Selector.open();  

  channel.configureBlocking(false);   

    channel.register(selector, SelectionKey.OP_ACCEPT);  // socket接收

  socketChannel.register(selector, SelectionKey.OP_READ); // 读

  while(true) {   

    int readyChannels = selector.select();   

    if(readyChannels == 0) continue;   

      Set selectedKeys = selector.selectedKeys();   

      Iterator keyIterator = selectedKeys.iterator();   

    while(keyIterator.hasNext()) {   

        SelectionKey key = keyIterator.next();   

    if(key.isAcceptable()) {   

      // a connection was accepted by a ServerSocketChannel. 

      ServerSocketChannel serverSocketChannel = SelectionKey.channel();

      SocketChannel socketChannel =   serverSocketChannel.accept(); 

      ByteBuffer buf = ByteBuffer.allocate(48);   

      socketChannel.read(buf);

       } else if (key.isConnectable()) {   

         // a connection was established with a remote server.   

            } else if (key.isReadable()) {

               // a channel is ready for reading   

            } else if (key.isWritable()) {   

      SocketChannel socketChannel =  SelectionKey.channel();

String newData = "New String to write to file..." + System.currentTimeMillis();   

      ByteBuffer buf = ByteBuffer.allocate(48);   

      buf.clear();   

      buf.put(newData.getBytes());   

      buf.flip();  // 将Buffer从写模式切换到读模式

      socketChannel.write(buf);

               // a channel is ready for writing   

         }

     keyIterator.remove();

  }   

}  

参考:http://www.iteye.com/magazines/132-Java-NIO#590

posted @ 2016-09-30 17:08  hyiam  阅读(246)  评论(0编辑  收藏  举报