• Java NIO (1)


    Java NIO (1)

    看了下java核心技术这本书 关于nio的部分介绍比较少,而且如果自己写服务器的话nio用的还是比较多,整理一下nio的资料

    java中nio主要是三个组件

    • Buffers
    • Channels
    • Selectors

    Buffer可以理解为缓冲区,NIO中的Buffer实现很多,一般常用的就是ByteBuffer

    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
    ByteBuffer mapedBuffer = ByteBuffer.allocateDirect(1024);
    

    一般情况下我们不必直接操作byteBuffer,都是用一个Channel来操作

    FileChannel fileChannel = FileChannel.open(path);
    int hadread = fileChannel.read(byteBuffer);
    

    调用flip切换为读写模式

    int hadread;
    while ((hadread=fileChannel.read(byteBuffer))>0){
    	byteBuffer.flip();
    	byte[] bytes = new byte[1024];
    	System.out.println(hadread);
    	byteBuffer.get(bytes,0,hadread);
    	for (int i = 0; i < hadread; i++) {
    		System.out.println(bytes[i]);
    	}
    	byteBuffer.flip();
    }
    

    如果遇到了网络编程,我们可能会需要类似于linux select epoll的功能,java nio已经为我们提供了

    一般情况下,我们使用单个线程处理多个Channels,因为如果线程过多,可能造成频繁的上下文切换导致开销过高(跟太频繁系统调用一个道理)

    selector就为我们提供了这样的功能

    不过selector只能跟SocketChannel一起使用,因为Channel必须处于非阻塞模式下

    FileChannel没有configureBlocking这个方法

    Selector selector = Selector.open();
    SocketChannel channel = server.accept();
    // 有新的连接并不代表这个通道就有数据,
    // 这里将这个新的 SocketChannel 注册到 Selector,监听 OP_READ 事件,等待数据
    channel.configureBlocking(false);
    //注册给某个selector
    SelectionKey key = channel.register(selector,
        Selectionkey.OP_READ);
    
    SelectionKey key;
    Channel  channel  = key.channel();
    Selector selector = key.selector();
    

    注册完之后,就可以像linux那样select

    //调用select
    // @return  The number of keys, possibly zero,
    // whose ready-operation sets were updated
    int readys = selector.select();
    //获取就绪事件的集合
    Set selectedKeys = selector.selectedKeys();
    

    //这里返回的是所有就绪事件,比如说可以读,可以写,可以连接

    //完整实例:

    Selector selector = Selector.open();
    channel.configureBlocking(false);
    SelectionKey key = channel.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.
        } 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()) {
            // a channel is ready for writing
        }
        keyIterator.remove();
      }
    }
    

    这个网站里面nio写的很好

    http://ifeve.com/overview/

    还有这个

    http://www.importnew.com/28021.html

  • 相关阅读:
    C# 调试程序时如何输入命令行参数
    C# 连接和操作SQL SERVER数据库
    在C#中读写INI配置文件(转)
    Visual Studio 项目中添加include, lib, dll库文件(*.h,*.lib,*.dll)
    Android系统Recovery工作原理
    Windows服务创建及安装
    C# WinForm窗口最小化到系统托盘
    C#文件操作
    C# 调用Windows API实现两个进程间的通信
    Linux转发性能评估与优化-转发瓶颈分析与解决方式(补遗)
  • 原文地址:https://www.cnblogs.com/stdpain/p/10665338.html
Copyright © 2020-2023  润新知