zoukankan      html  css  js  c++  java
  • nio笔记

    http://blog.csdn.net/z69183787/article/category/2191483此人的博客

     首先你要知道阻塞和非阻塞的概念,阻塞体现在这个线程不能干别的了,只能在这里等着。非阻塞体现在这个线程可以去干别的,不需要一直在这等着。
    说NIO的非阻塞原理之前,我们需要先说一下传统的io。传统的IO是按字节传输的,即每次传输一个字节。为了提高数据传输效率,引进了带缓冲区得输入输出模式,这样每次就可以传输大量的字节数,

    但是,会导致在读(写)缓冲区没有满的情况下,程序会一直等待,直到满或者关闭流才能读取(写入)。这样导致程序阻塞,降低了程序的执行效率。、

    非阻塞模式  使一个线程可以同时处理多个通道, 通道accept  read  write 没有连接,读写数据不够或者没有时都直接返回,不用阻塞等待。

    同步:线程需要的等待返回结果  

    异步:如果有返回结果,线程会得到通知

    阻塞:方法不会立即返回结果

    非阻塞:不论是否有结果   方法都会返回一个信息

    1.使用通道:  fileinputstream.getChannel()    打开的文件通道只有读权限,没有写权限,如果写,报异常,不要执行写操作。

       注意读写权限问题。

    FileInputStream input = new FileInputStream (fileName);

    FileChannel channel = input.getChannel( );

    // This will compile but will throw an IOException

    // because the underlying file is read-only

    channel.write (buffer);

    2.只有流通道: sockets  pipes可以非阻塞模式, 文件通道总是阻塞式的, 文件io最强大之处在于:异步io,一个进程可以请求多个io操作。

    阻塞是I/O操作阻塞,      当前通道正在执行io操作,其他io操作则阻塞,  非阻塞则会返回null

    3.文件 进程级别。

    4.reigster 注册通道时,如果已经注册过,则更新,如果已经注册且 selectionkey已经被cancel, 则报异常。

    key.cancel();
    ssc.register(selector, SelectionKey.OP_ACCEPT);

    抛异常

     一个通道可以被注册到多个选择器上,但对每个选择器而言只能被注册一次。

    5.每次迭代的末尾调用keyIterator.remove()

    例如:首次调用select()方法,如果有一个通道变成就绪状态,返回了1,若再次调用select()方法,如果另一个通道就绪了,它会再次返回1。如果对第一个就绪的channel没有做任何操作,现在就有两个就绪的通道,但在每次select()方法调用之间,只有一个通道就绪了。

    6.向selector注册通道时,通道必须是非阻塞模式

    configblocking(false)

    注意点:

    1.it.remove();

    2.想关闭channel, 用key.cancel()

    key.cancel()  下次select会取消这个key相关的信息, channel也会注销

    3.多线程处理时:

    key.interestOps(key.interestOps() & (~SelectionKey.OP_READ));

    处理完成后

    key.interestOps(key.interestOps() | SelectionKey.OP_READ);
    key.selector().wakeup();

    4.   流末尾返回-1;     while(buffer.hasremaining())写数据 

    while(source.read(buffer) != -1) {
    buffer.flip();
    while(buffer.hasRemaining()) {
    dest.write(buffer);
    }
    buffer.clear();
    }

    5.

     String question = new String(readBuffer.array());    array 是返回整个buffer内容

     CharBuffer charBuffer = CharsetHelper.decode(readBuffer);   返回position--limit的内容

    6.

    /*当客户端channel关闭后,会不断收到read事件,但没有消息,即read方法返回-1                

    * 所以这时服务器端也需要关闭channel,避免无限无效的处理*/    

    try{

      if((channel.read(buffer) )  > 0 ){

      } else {

        //关闭channel, 因为客户端已经关闭channel或者已经异常

        channel.close();

      }

    }catch(Exception e){

      if(channel != null) {

        channel.close();

      }

    }

    7.

     channel.write(CharsetHelper.encode(CharBuffer.wrap(answer))); 

    8

    .channel.open   configblocking(false)   connect()  不要简写或改顺序

    1. if(selector == null)   
    2.     selector = Selector.open();   
    3. SocketChannel channel = SocketChannel.open();   
    4. channel.configureBlocking(false);   
    5. channel.connect(new InetSocketAddress("localhost", 1234));   
    6. channel.register(selector, SelectionKey.OP_CONNECT);  
    1. //连接事件   
    2. if(key.isConnectable()) {   
    3.     SocketChannel socketChannel = (SocketChannel) key.channel();   
    4.     if(socketChannel.isConnectionPending())   
    5.         socketChannel.finishConnect();   
    6.     socketChannel.write(ByteBuffer.wrap(serverFileName.getBytes()));//向服务器发信息,信息中即服务器上的文件名   
    7.     socketChannel.register(selector, SelectionKey.OP_READ);   
    8. }  
  • 相关阅读:
    Prototype的深度探索
    MySQL LIST分区
    CentOS6下Haproxy的安装配置
    haproxy做TCP层的负载均衡
    Shape Control for .NET
    如何通过 HSB 颜色模式构建夜间模式
    使用ICSharpCode.TextEditor制作一个语法高亮显示的XML编辑器
    Roslyn介绍
    信息安全名词
    用彩虹表破解MD5、LM Hash等复杂加密密码
  • 原文地址:https://www.cnblogs.com/wuer888/p/7300499.html
Copyright © 2011-2022 走看看