aio_aiot - CSDN
aio 订阅
AIO:所有的集成在一个里面(All In One). 如:国内知名的制造业ERP提供商普实软件公司(pushsoft), 出品的AIO7系统, 创新的将ERP、HR、OA、BI等功能集成在一起, 并命名为AIO7. 展开全文
AIO:所有的集成在一个里面(All In One). 如:国内知名的制造业ERP提供商普实软件公司(pushsoft), 出品的AIO7系统, 创新的将ERP、HR、OA、BI等功能集成在一起, 并命名为AIO7.
信息
AIO用途
消费者的态度、兴趣和观点
外文名
Asynchronous Input/Output
释    义
All In One
中文名
AIO
AIO简介
AIO就是All In One(一体)的意思。AIO:Asynchronous Input/Output异步输入/输出是任何特殊输入/输出流异步输入/输出是任何特殊输入/输出流(同步和异步输入/输出)两个基本操作模式之一。在异步模式中,自然的输入/输出事务不必须和一个程序的输入/输出状态同步或互锁。例如,一个用户或一个打字员应该被允许将信息提前输入系统中来执行能够使用它们的读状态。每个读状态的执行仅仅将下一个等待信息从一个输入缓冲器中去除。这个异步输入的例子类似于已经用于唱片、磁带等中的缓冲提前读方案。一个异步输出的例子是在一个核心缓冲器中收集直到一些物理记录大小被找到。
收起全文
精华内容
参与话题
  • JAVA AIO编程

    2019-04-25 19:39:27
    AIO 异步非阻塞的编程方式 进行读写操作的时候,只需要调用api的read和write方法即可,这两种方法均为异步的。对于读操作而言,当有流可读取的时候,操作系统会将可读的流传入read方法的缓存区,并通知应用;对于写...

    Asynchronous IO: 异步非阻塞的编程方式
    与NIO不同,当进行读写操作时,只须直接调用API的read或write方法即可。这两种方法均为异步的,对于读操作而言,当有流可读取时,操作系统会将可读的流传入read方法的缓冲区,并通知应用程序;对于写操作而言,当操作系统将write方法传递的流写入完毕时,操作系统主动通知应用程序。即可以理解为,read/write方法都是异步的,完成后会主动调用回调函数。在JDK1.7中,这部分内容被称作NIO.2,主要在java.nio.channels包下增加了下面四个异步通道:
    AsynchronousSocketChannel
    AsynchronousServerSocketChannel
    AsynchronousFileChannel
    AsynchronousDatagramChannel
    异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O 请求都是由OS
    先完成了再通知服务器应用去启动线程进行处理。
    AIO 方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调
    用OS 参与并发操作,编程比较复杂,JDK7 开始支持。

    在这里插入图片描述

    package aio;
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.AsynchronousSocketChannel;
    import java.util.Scanner;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.Future;
    
    public class AIOClient {
    
        private AsynchronousSocketChannel channel;
    
        public AIOClient(String host, int port){
            init(host, port);
        }
    
        private void init(String host, int port){
            try {
                // 开启通道
                channel = AsynchronousSocketChannel.open();
                // 发起请求,建立连接。
                channel.connect(new InetSocketAddress(host, port));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public void write(String line){
            try {
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                buffer.put(line.getBytes("UTF-8"));
                buffer.flip();
                channel.write(buffer);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
    
        public void read(){
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            try {
                // read方法是异步方法,OS实现的。get方法是一个阻塞方法,会等待OS处理结束后再返回。
                channel.read(buffer).get();
                // channel.read(dst, attachment, handler);
                buffer.flip();
                System.out.println("from server : " + new String(buffer.array(), "UTF-8"));
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
    
        public void doDestory(){
            if(null != channel){
                try {
                    channel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) {
            AIOClient client = new AIOClient("localhost", 9999);
            try{
                System.out.print("enter message send to server > ");
                Scanner s = new Scanner(System.in);
                String line = s.nextLine();
                client.write(line);
                client.read();
            }finally{
                client.doDestory();
            }
        }
    
    }
    
    
    package aio;
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.channels.AsynchronousChannelGroup;
    import java.nio.channels.AsynchronousServerSocketChannel;
    import java.util.Scanner;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    public class AIOServer {
    
        // 线程池, 提高服务端效率。
        private ExecutorService service;
        // 线程组
        // private AsynchronousChannelGroup group;
        // 服务端通道, 针对服务器端定义的通道。
        private AsynchronousServerSocketChannel serverChannel;
    
        public AIOServer(int port){
            init(9999);
        }
    
        private void init(int port){
            try {
                System.out.println("server starting at port : " + port + " ...");
                // 定长线程池
                service = Executors.newFixedThreadPool(4);
                /* 使用线程组
                group = AsynchronousChannelGroup.withThreadPool(service);
                serverChannel = AsynchronousServerSocketChannel.open(group);
                */
                // 开启服务端通道, 通过静态方法创建的。
                serverChannel = AsynchronousServerSocketChannel.open();
                // 绑定监听端口, 服务器启动成功,但是未监听请求。
                serverChannel.bind(new InetSocketAddress(port));
                System.out.println("server started.");
                // 开始监听
                // accept(T attachment, CompletionHandler<AsynchronousSocketChannel, ? super T>)
                // AIO开发中,监听是一个类似递归的监听操作。每次监听到客户端请求后,都需要处理逻辑开启下一次的监听。
                // 下一次的监听,需要服务器的资源继续支持。
                serverChannel.accept(this, new AIOServerHandler());
                try {
                    TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            new AIOServer(9999);
        }
    
        public ExecutorService getService() {
            return service;
        }
    
        public void setService(ExecutorService service) {
            this.service = service;
        }
    
        public AsynchronousServerSocketChannel getServerChannel() {
            return serverChannel;
        }
    
        public void setServerChannel(AsynchronousServerSocketChannel serverChannel) {
            this.serverChannel = serverChannel;
        }
    
    }
    
    
    package aio;
    import java.io.UnsupportedEncodingException;
    import java.nio.ByteBuffer;
    import java.nio.channels.AsynchronousSocketChannel;
    import java.nio.channels.CompletionHandler;
    import java.util.Scanner;
    import java.util.concurrent.ExecutionException;
    
    public class AIOServerHandler implements CompletionHandler<AsynchronousSocketChannel, AIOServer> {
    
        /**
         * 业务处理逻辑, 当请求到来后,监听成功,应该做什么。
         * 一定要实现的逻辑: 为下一次客户端请求开启监听。accept方法调用。
         * result参数 : 就是和客户端直接建立关联的通道。
         *  无论BIO、NIO、AIO中,一旦连接建立,两端是平等的。
         *  result中有通道中的所有相关数据。如:OS操作系统准备好的读取数据缓存,或等待返回数据的缓存。
         */
        @Override
        public void completed(AsynchronousSocketChannel result, AIOServer attachment) {
            // 处理下一次的客户端请求。类似递归逻辑
            attachment.getServerChannel().accept(attachment, this);
            doRead(result);
        }
    
        /**
         * 异常处理逻辑, 当服务端代码出现异常的时候,做什么事情。
         */
        @Override
        public void failed(Throwable exc, AIOServer attachment) {
            exc.printStackTrace();
        }
    
        /**
         * 真实项目中,服务器返回的结果应该是根据客户端的请求数据计算得到的。不是等待控制台输入的。
         * @param result
         */
        private void doWrite(AsynchronousSocketChannel result){
            try {
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                System.out.print("enter message send to client > ");
                Scanner s = new Scanner(System.in);
                String line = s.nextLine();
                buffer.put(line.getBytes("UTF-8"));
                // 重点:必须复位,必须复位,必须复位
                buffer.flip();
                // write方法是一个异步操作。具体实现由OS实现。 可以增加get方法,实现阻塞,等待OS的写操作结束。
                result.write(buffer);
                // result.write(buffer).get(); // 调用get代表服务端线程阻塞,等待写操作完成
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }/* catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }*/
        }
    
        private void doRead(final AsynchronousSocketChannel channel){
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            /*
             * 异步读操作, read(Buffer destination, A attachment,
             *                    CompletionHandler<Integer, ? super A> handler)
             * destination - 目的地, 是处理客户端传递数据的中转缓存。 可以不使用。
             * attachment - 处理客户端传递数据的对象。 通常使用Buffer处理。
             * handler - 处理逻辑
             */
            channel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
    
                /**
                 * 业务逻辑,读取客户端传输数据
                 * attachment - 在completed方法执行的时候,OS已经将客户端请求的数据写入到Buffer中了。
                 *  但是未复位(flip)。 使用前一定要复位。
                 */
                @Override
                public void completed(Integer result, ByteBuffer attachment) {
                    try {
                        System.out.println(attachment.capacity());
                        // 复位
                        attachment.flip();
                        System.out.println("from client : " + new String(attachment.array(), "UTF-8"));
                        doWrite(channel);
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                }
    
                @Override
                public void failed(Throwable exc, ByteBuffer attachment) {
                    exc.printStackTrace();
                }
            });
        }
    
    }
    
    
    展开全文
  • java aio和nio的区别

    万次阅读 多人点赞 2018-08-31 00:35:39
    AIO 是彻底的异步通信。 NIO 是同步非阻塞通信。 有一个经典的举例。烧开水。 假设有这么一个场景,有一排水壶(客户)在烧水。 AIO的做法是,每个水壶上装一个开关,当水开了以后会提醒对应的线程去处理。 NIO的...

    AIO 是彻底的异步通信。
    NIO 是同步非阻塞通信。
    有一个经典的举例。烧开水。
    假设有这么一个场景,有一排水壶(客户)在烧水。

    AIO的做法是,每个水壶上装一个开关,当水开了以后会提醒对应的线程去处理。
    NIO的做法是,叫一个线程不停的循环观察每一个水壶,根据每个水壶当前的状态去处理。
    BIO的做法是,叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。

    可以看出AIO是最聪明省力,NIO相对省力,叫一个人就能看所有的壶,BIO最愚蠢,劳动力低下。

    简单的描述一下BIO的服务端通信模型:采用BIO通信模型的服务端,通常由一个独立的Acceptor线程负责监听客户端的连接,它接收到客户端连接请求之后为每个客户端创建一个新的线程进行链路处理 处理完成后,通过输出流返回应答给客户端,线程销毁。即典型的一请求一应答通宵模型。

    01

    刚开始人们为了解决上面,高并发下服务器建立线程过多而枯竭,有人就想出了使用线程池来控制建立线程的数量,不至于服务器挂掉,于是就有了伪异步的io编程

    一(1)、伪异步I/O编程

      为了改进上面这种一连接一线程的模型,我们可以使用线程池来管理这些线程,实现1个或多个线程处理N个客户端的模型(但是底层还是使用的同步阻塞I/O),通常被称为“伪异步I/O模型“。

    02

     我们知道,如果使用CachedThreadPool线程池(不限制线程数量),其实除了能自动帮我们管理线程(复用),看起来也就像是1:1的客户端:线程数模型,而使用FixedThreadPool我们就有效的控制了线程的最大数量,保证了系统有限的资源的控制,实现了N:M的伪异步I/O模型。

     但是,正因为限制了线程数量,如果发生大量并发请求,超过最大数量的线程就只能等待,直到线程池中的有空闲的线程可以被复用。而对Socket的输入流就行读取时,会一直阻塞,直到发生:

    有数据可读

    可用数据以及读取完毕

    发生空指针或I/O异常

    所以在读取数据较慢时(比如数据量大、网络传输慢等),大量并发的情况下,其他接入的消息,只能一直等待,这就是最大的弊端。而后面即将介绍的NIO,就能解决这个难题。

     二、NIO 编程(非阻塞I/O)

    JDK 1.4中的java.nio.*包中引入新的Java I/O库,其目的是提高速度。实际上,“旧”的I/O包已经使用NIO重新实现过,即使我们不显式的使用NIO编程,也能从中受益。速度的提高在文件I/O和网络I/O中都可能会发生,但本文只讨论后者。

    (1)缓冲区buffer

        buffer是一个对象,包含了读取和写入的数据,在nio中,所有的数据都是通过缓冲区来处理的。在写入数据时,也是写入到缓冲区中。任何时候访问NIO中的数据,都是通过缓冲区进行操作。

        缓冲区实际是一个数组结构,并提供了对数据结构化访问以及维护读写位置等信息。

        8种基本类型都有相应的缓冲区:ByteBuffe、CharBuffer、 ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer。他们实现了相同的接口:Buffer。

    (2)通道channel

        我们对数据的读取和写入都要通过channel,它就像水管一样,是一个通道。通道不同于流的地方就是通道是双向的,可以用于读、写和同时读写操作。

        底层的操作系统的通道一般都是全双工的,所以全双工的Channel比流能更好的映射底层操作系统的API。

        channel主要有2大类:

           selectablechannel 用于用户网络的读写(后面代码会涉及的ServerSocketChannel和SocketChannel都是SelectableChannel的子类。)

           Filechannel 用于文件的操作

    (3)多路复用器 Selector

        Selector是Java  NIO 编程的基础。

       提供选择已经就绪的任务的能力:Selector会不断轮询注册在其上的Channel,如果某个Channel上面发生读或者写事件,这个Channel就处于就绪状态,会被Selector轮询出来,然后通过SelectionKey可以获取就绪Channel的集合,进行后续的I/O操作。

       一个Selector可以同时轮询多个Channel,因为JDK使用了epoll()代替传统的select实现,所以没有最大连接句柄1024/2048的限制。所以,只需要一个线程负责Selector的轮询,就可以接入成千上万的客户端。

    (4)NIO服务端

      创建NIO服务端的主要步骤如下:

     

    1.   打开ServerSocketChannel,监听客户端连接
    2.  绑定监听端口,设置连接为非阻塞模式
    3.  创建Reactor线程,创建多路复用器并启动线程
    4.  将ServerSocketChannel注册到Reactor线程中的Selector上,监听ACCEPT事件
    5.  Selector轮询准备就绪的key
    6.  Selector监听到新的客户端接入,处理新的接入请求,完成TCP三次握手,简历物理链路
    7.  设置客户端链路为非阻塞模式
    8.  将新接入的客户端连接注册到Reactor线程的Selector上,监听读操作,读取客户端发送的网络消息
    9.  异步读取客户端消息到缓冲区
    10.  对Buffer编解码,处理半包消息,将解码成功的消息封装成Task
    11.  将应答消息编码为Buffer,调用SocketChannel的write将消息异步发送给客户端

        所以不能保证一次能吧需要发送的数据发送完,此时就会出现写半包的问题。我们需要注册写操作,不断轮询Selector将没有发送完的消息发送完毕,然后通过Buffer的hasRemain()方法判断消息是否发送完成。

    (5)NIO客户端

    三、AIO编程

       NIO 2.0引入了新的异步通道的概念,并提供了异步文件通道和异步套接字通道的实现。

    异步的套接字通道时真正的异步非阻塞I/O,对应于UNIX网络编程中的事件驱动I/O(AIO)。他不需要过多的Selector对注册的通道进行轮询即可实现异步读写,从而简化了NIO的编程模型。

    API比NIO的使用起来真的简单多了,主要就是监听、读、写等各种CompletionHandler。此处本应有一个WriteHandler的,确实,我们在ReadHandler中,以一个匿名内部类实现了它。

    AIO是真正的异步非阻塞的,所以,在面对超级大量的客户端,更能得心应手

    展开全文
  • IO模型、NIO与AIO入门

    2019-11-29 12:05:50
    详细地把IO流、NIO与AIO的基础知识点讲清楚。 课程资料:https://pan.baidu.com/s/1lxkUNTLCG6F26MgylgEi7w 提取码:qpwe  学习路线:
  • AIO原理

    千次阅读 2016-05-05 15:49:15
    Java nio 2.0的主要改进就是引入了异步IO(包括文件...首先看下为了支持AIO引入的新的类和接口:  java.nio.channels.AsynchronousChannel  标记一个channel支持异步IO操作。  java.nio.channels.Asynchronou

     Java nio 2.0的主要改进就是引入了异步IO(包括文件和网络),这里主要介绍下异步网络IO API的使用以及框架的设计,以TCP服务端为例。首先看下为了支持AIO引入的新的类和接口:

     java.nio.channels.AsynchronousChannel
           标记一个channel支持异步IO操作。

     java.nio.channels.AsynchronousServerSocketChannel
           ServerSocket的aio版本,创建TCP服务端,绑定地址,监听端口等。

     java.nio.channels.AsynchronousSocketChannel
           面向流的异步socket channel,表示一个连接。

     java.nio.channels.AsynchronousChannelGroup
           异步channel的分组管理,目的是为了资源共享。一个AsynchronousChannelGroup绑定一个线程池,这个线程池执行两个任务:处理IO事件和派发CompletionHandler。AsynchronousServerSocketChannel创建的时候可以传入一个 AsynchronousChannelGroup,那么通过AsynchronousServerSocketChannel创建的 AsynchronousSocketChannel将同属于一个组,共享资源。

     java.nio.channels.CompletionHandler
           异步IO操作结果的回调接口,用于定义在IO操作完成后所作的回调工作。AIO的API允许两种方式来处理异步操作的结果:返回的Future模式或者注册CompletionHandler,我更推荐用CompletionHandler的方式,这些handler的调用是由 AsynchronousChannelGroup的线程池派发的。显然,线程池的大小是性能的关键因素。AsynchronousChannelGroup允许绑定不同的线程池,通过三个静态方法来创建:

    Java代码  收藏代码
    1. public static AsynchronousChannelGroup withFixedThreadPool(int nThreads,  
    2.                                                               ThreadFactory threadFactory)  
    3.        throws IOException  
    4.   
    5. public static AsynchronousChannelGroup withCachedThreadPool(ExecutorService executor,  
    6.                                                                int initialSize)  
    7.   
    8. public static AsynchronousChannelGroup withThreadPool(ExecutorService executor)  
    9.        throws IOException  
     

         需要根据具体应用相应调整,从框架角度出发,需要暴露这样的配置选项给用户。

         在介绍完了aio引入的TCP的主要接口和类之后,我们来设想下一个aio框架应该怎么设计。参考非阻塞nio框架的设计,一般都是采用Reactor模式,Reacot负责事件的注册、select、事件的派发;相应地,异步IO有个Proactor模式,Proactor负责 CompletionHandler的派发,查看一个典型的IO写操作的流程来看两者的区别:

         Reactor:  send(msg) -> 消息队列是否为空,如果为空  -> 向Reactor注册OP_WRITE,然后返回 -> Reactor select -> 触发Writable,通知用户线程去处理 ->先注销Writable(很多人遇到的cpu 100%的问题就在于没有注销),处理Writeable,如果没有完全写入,继续注册OP_WRITE。注意到,写入的工作还是用户线程在处理。
         Proactor: send(msg) -> 消息队列是否为空,如果为空,发起read异步调用,并注册CompletionHandler,然后返回。 -> 操作系统负责将你的消息写入,并返回结果(写入的字节数)给Proactor -> Proactor派发CompletionHandler。可见,写入的工作是操作系统在处理,无需用户线程参与。事实上在aio的API 中,AsynchronousChannelGroup就扮演了Proactor的角色

        CompletionHandler有三个方法,分别对应于处理成功、失败、被取消(通过返回的Future)情况下的回调处理:

    Java代码  收藏代码
    1. public interface CompletionHandler<V,A> {  
    2.   
    3.      void completed(V result, A attachment);  
    4.   
    5.     void failed(Throwable exc, A attachment);  
    6.   
    7.      
    8.     void cancelled(A attachment);  
    9. }  
     


        其中的泛型参数V表示IO调用的结果,而A是发起调用时传入的attchment。

        在初步介绍完aio引入的类和接口后,我们看看一个典型的tcp服务端是怎么启动的,怎么接受连接并处理读和写,这里引用的代码都是yanf4j 的aio分支中的代码,可以从svn checkout,svn地址: http://yanf4j.googlecode.com/svn/branches/yanf4j-aio

        第一步,创建一个AsynchronousServerSocketChannel,创建之前先创建一个 AsynchronousChannelGroup,上文提到AsynchronousServerSocketChannel可以绑定一个 AsynchronousChannelGroup,那么通过这个AsynchronousServerSocketChannel建立的连接都将同属于一个AsynchronousChannelGroup并共享资源:

    Java代码  收藏代码
    1. this.asynchronousChannelGroup = AsynchronousChannelGroup  
    2.                     .withCachedThreadPool(Executors.newCachedThreadPool(),  
    3.                             this.threadPoolSize);  

         然后初始化一个AsynchronousServerSocketChannel,通过open方法:

    Java代码  收藏代码
    1. this.serverSocketChannel = AsynchronousServerSocketChannel  
    2.                 .open(this.asynchronousChannelGroup);  
     

        通过nio 2.0引入的SocketOption类设置一些TCP选项:

    Java代码  收藏代码
    1. this.serverSocketChannel  
    2.                     .setOption(  
    3.                             StandardSocketOption.SO_REUSEADDR,true);  
    4. this.serverSocketChannel  
    5.                     .setOption(  
    6.                             StandardSocketOption.SO_RCVBUF,16*1024);  
     


        绑定本地地址:

    Java代码  收藏代码
    1. this.serverSocketChannel  
    2.                     .bind(new InetSocketAddress("localhost",8080), 100);  
     

       
        其中的100用于指定等待连接的队列大小(backlog)。完了吗?还没有,最重要的监听工作还没开始,监听端口是为了等待连接上来以便accept产生一个AsynchronousSocketChannel来表示一个新建立的连接,因此需要发起一个accept调用,调用是异步的,操作系统将在连接建立后,将最后的结果——AsynchronousSocketChannel返回给你:

    Java代码  收藏代码
    1. public void pendingAccept() {  
    2.         if (this.started && this.serverSocketChannel.isOpen()) {  
    3.             this.acceptFuture = this.serverSocketChannel.accept(null,  
    4.                     new AcceptCompletionHandler());  
    5.   
    6.         } else {  
    7.             throw new IllegalStateException("Controller has been closed");  
    8.         }  
    9.     }  
     


       注意,重复的accept调用将会抛出PendingAcceptException,后文提到的read和write也是如此。accept方法的第一个参数是你想传给CompletionHandler的attchment,第二个参数就是注册的用于回调的CompletionHandler,最后返回结果Future<AsynchronousSocketChannel>。你可以对future做处理,这里采用更推荐的方式就是注册一个CompletionHandler。那么accept的CompletionHandler中做些什么工作呢?显然一个赤裸裸的 AsynchronousSocketChannel是不够的,我们需要将它封装成session,一个session表示一个连接(mina里就叫 IoSession了),里面带了一个缓冲的消息队列以及一些其他资源等。在连接建立后,除非你的服务器只准备接受一个连接,不然你需要在后面继续调用pendingAccept来发起另一个accept请求

    Java代码  收藏代码
    1. private final class AcceptCompletionHandler implements  
    2.             CompletionHandler<AsynchronousSocketChannel, Object> {  
    3.   
    4.         @Override  
    5.         public void cancelled(Object attachment) {  
    6.             logger.warn("Accept operation was canceled");  
    7.         }  
    8.   
    9.         @Override  
    10.         public void completed(AsynchronousSocketChannel socketChannel,  
    11.                 Object attachment) {  
    12.             try {  
    13.                 logger.debug("Accept connection from "  
    14.                         + socketChannel.getRemoteAddress());  
    15.                 configureChannel(socketChannel);  
    16.                 AioSessionConfig sessionConfig = buildSessionConfig(socketChannel);  
    17.                 Session session = new AioTCPSession(sessionConfig,  
    18.                         AioTCPController.this.configuration  
    19.                                 .getSessionReadBufferSize(),  
    20.                         AioTCPController.this.sessionTimeout);  
    21.                 session.start();  
    22.                 registerSession(session);  
    23.             } catch (Exception e) {  
    24.                 e.printStackTrace();  
    25.                 logger.error("Accept error", e);  
    26.                 notifyException(e);  
    27.             } finally {  
    28.                 <strong>pendingAccept</strong>();  
    29.             }  
    30.         }  
    31.   
    32.         @Override  
    33.         public void failed(Throwable exc, Object attachment) {  
    34.             logger.error("Accept error", exc);  
    35.             try {  
    36.                 notifyException(exc);  
    37.             } finally {  
    38.                 <strong>pendingAccept</strong>();  
    39.             }  
    40.         }  
    41.     }  
     

      
        注意到了吧,我们在failed和completed方法中在最后都调用了pendingAccept来继续发起accept调用,等待新的连接上来。有的同学可能要说了,这样搞是不是递归调用,会不会堆栈溢出?实际上不会,因为发起accept调用的线程与CompletionHandler回调的线程并非同一个,不是一个上下文中,两者之间没有耦合关系。要注意到,CompletionHandler的回调共用的是 AsynchronousChannelGroup绑定的线程池,因此千万别在CompletionHandler回调方法中调用阻塞或者长时间的操作,例如sleep,回调方法最好能支持超时,防止线程池耗尽。

        连接建立后,怎么读和写呢?回忆下在nonblocking nio框架中,连接建立后的第一件事是干什么?注册OP_READ事件等待socket可读。异步IO也同样如此,连接建立后马上发起一个异步read调用,等待socket可读,这个是Session.start方法中所做的事情:

    Java代码  收藏代码
    1. public class AioTCPSession {  
    2.     protected void start0() {  
    3.         pendingRead();  
    4.     }  
    5.   
    6.     protected final void pendingRead() {  
    7.         if (!isClosed() && this.asynchronousSocketChannel.isOpen()) {  
    8.             if (!this.readBuffer.hasRemaining()) {  
    9.                 this.readBuffer = ByteBufferUtils  
    10.                         .increaseBufferCapatity(this.readBuffer);  
    11.             }  
    12.             this.readFuture = this.asynchronousSocketChannel.read(  
    13.                     this.readBuffer, thisthis.readCompletionHandler);  
    14.         } else {  
    15.             throw new IllegalStateException(  
    16.                     "Session Or Channel has been closed");  
    17.         }  
    18.     }  
    19.      
    20. }  
     

         AsynchronousSocketChannel的read调用与AsynchronousServerSocketChannel的accept调用类似,同样是非阻塞的,返回结果也是一个Future,但是写的结果是整数,表示写入了多少字节,因此read调用返回的是 Future<Integer>,方法的第一个参数是读的缓冲区,操作系统将IO读到数据拷贝到这个缓冲区,第二个参数是传递给 CompletionHandler的attchment,第三个参数就是注册的用于回调的CompletionHandler。这里保存了read的结果Future,这是为了在关闭连接的时候能够主动取消调用,accept也是如此。现在可以看看read的CompletionHandler的实现:

    Java代码  收藏代码
    1. public final class ReadCompletionHandler implements  
    2.         CompletionHandler<Integer, AbstractAioSession> {  
    3.   
    4.     private static final Logger log = LoggerFactory  
    5.             .getLogger(ReadCompletionHandler.class);  
    6.     protected final AioTCPController controller;  
    7.   
    8.     public ReadCompletionHandler(AioTCPController controller) {  
    9.         this.controller = controller;  
    10.     }  
    11.   
    12.     @Override  
    13.     public void cancelled(AbstractAioSession session) {  
    14.         log.warn("Session(" + session.getRemoteSocketAddress()  
    15.                 + ") read operation was canceled");  
    16.     }  
    17.   
    18.     @Override  
    19.     public void completed(Integer result, AbstractAioSession session) {  
    20.         if (log.isDebugEnabled())  
    21.             log.debug("Session(" + session.getRemoteSocketAddress()  
    22.                     + ") read +" + result + " bytes");  
    23.         if (result < 0) {  
    24.             session.close();  
    25.             return;  
    26.         }  
    27.         try {  
    28.             if (result > 0) {  
    29.                 session.updateTimeStamp();  
    30.                 session.getReadBuffer().flip();  
    31.                 session.decode();  
    32.                 session.getReadBuffer().compact();  
    33.             }  
    34.         } finally {  
    35.             try {  
    36.                 session.pendingRead();  
    37.             } catch (IOException e) {  
    38.                 session.onException(e);  
    39.                 session.close();  
    40.             }  
    41.         }  
    42.         controller.checkSessionTimeout();  
    43.     }  
    44.   
    45.     @Override  
    46.     public void failed(Throwable exc, AbstractAioSession session) {  
    47.         log.error("Session read error", exc);  
    48.         session.onException(exc);  
    49.         session.close();  
    50.     }  
    51.   
    52. }  
     

       如果IO读失败,会返回失败产生的异常,这种情况下我们就主动关闭连接,通过session.close()方法,这个方法干了两件事情:关闭channel和取消read调用:

    Java代码  收藏代码
    1. if (null != this.readFuture) {  
    2.             this.readFuture.cancel(true);  
    3.         }  
    4. this.asynchronousSocketChannel.close();  
     

       在读成功的情况下,我们还需要判断结果result是否小于0,如果小于0就表示对端关闭了,这种情况下我们也主动关闭连接并返回。如果读到一定字节,也就是result大于0的情况下,我们就尝试从读缓冲区中decode出消息,并派发给业务处理器的回调方法,最终通过pendingRead继续发起read调用等待socket的下一次可读。可见,我们并不需要自己去调用channel来进行IO读,而是操作系统帮你直接读到了缓冲区,然后给你一个结果表示读入了多少字节,你处理这个结果即可。而nonblocking IO框架中,是reactor通知用户线程socket可读了,然后用户线程自己去调用read进行实际读操作。这里还有个需要注意的地方,就是decode出来的消息的派发给业务处理器工作最好交给一个线程池来处理,避免阻塞group绑定的线程池。
      
       IO写的操作与此类似,不过通常写的话我们会在session中关联一个缓冲队列来处理,没有完全写入或者等待写入的消息都存放在队列中,队列为空的情况下发起write调用:

    Java代码  收藏代码
    1. protected void write0(WriteMessage message) {  
    2.       boolean needWrite = false;  
    3.       synchronized (this.writeQueue) {  
    4.           needWrite = this.writeQueue.isEmpty();  
    5.           this.writeQueue.offer(message);  
    6.       }  
    7.       if (needWrite) {  
    8.           pendingWrite(message);  
    9.       }  
    10.   }  
    11.   
    12.   protected final void pendingWrite(WriteMessage message) {  
    13.       message = preprocessWriteMessage(message);  
    14.       if (!isClosed() && this.asynchronousSocketChannel.isOpen()) {  
    15.           this.asynchronousSocketChannel.write(message.getWriteBuffer(),  
    16.                   thisthis.writeCompletionHandler);  
    17.       } else {  
    18.           throw new IllegalStateException(  
    19.                   "Session Or Channel has been closed");  
    20.       }  
    21.   }  
     

        write调用返回的结果与read一样是一个Future<Integer>,而write的CompletionHandler处理的核心逻辑大概是这样:

    Java代码  收藏代码
    1. @Override  
    2.     public void completed(Integer result, AbstractAioSession session) {  
    3.         if (log.isDebugEnabled())  
    4.             log.debug("Session(" + session.getRemoteSocketAddress()  
    5.                     + ") writen " + result + " bytes");  
    6.                   
    7.         WriteMessage writeMessage;  
    8.         Queue<WriteMessage> writeQueue = session.getWriteQueue();  
    9.         synchronized (writeQueue) {  
    10.             writeMessage = writeQueue.peek();  
    11.             if (writeMessage.getWriteBuffer() == null  
    12.                     || !writeMessage.getWriteBuffer().hasRemaining()) {  
    13.                 writeQueue.remove();  
    14.                 if (writeMessage.getWriteFuture() != null) {  
    15.                     writeMessage.getWriteFuture().setResult(Boolean.TRUE);  
    16.                 }  
    17.                 try {  
    18.                     session.getHandler().onMessageSent(session,  
    19.                             writeMessage.getMessage());  
    20.                 } catch (Exception e) {  
    21.                     session.onException(e);  
    22.                 }  
    23.                 writeMessage = writeQueue.peek();  
    24.             }  
    25.         }  
    26.         if (writeMessage != null) {  
    27.             try {  
    28.                 session.pendingWrite(writeMessage);  
    29.             } catch (IOException e) {  
    30.                 session.onException(e);  
    31.                 session.close();  
    32.             }  
    33.         }  
    34.     }  
     


       compete方法中的result就是实际写入的字节数,然后我们判断消息的缓冲区是否还有剩余,如果没有就将消息从队列中移除,如果队列中还有消息,那么继续发起write调用。

       重复一下,这里引用的代码都是yanf4j aio分支中的源码,感兴趣的朋友可以直接check out出来看看:http://yanf4j.googlecode.com/svn/branches/yanf4j-aio
       在引入了aio之后,java对于网络层的支持已经非常完善,该有的都有了,java也已经成为服务器开发的首选语言之一。java的弱项在于对内存的管理上,由于这一切都交给了GC,因此在高性能的网络服务器上还是Cpp的天下。java这种单一堆模型比之erlang的进程内堆模型还是有差距,很难做到高效的垃圾回收和细粒度的内存管理。

       这里仅仅是介绍了aio开发的核心流程,对于一个网络框架来说,还需要考虑超时的处理、缓冲buffer的处理、业务层和网络层的切分、可扩展性、性能的可调性以及一定的通用性要求。

    展开全文
  • AIO 区别及联系 各自适用场景 使用方式 IO 什么是IO? 它是指计算机与外部世界或者一个程序与计算机的其余部分的之间的接口。它对于任何计算机系统都非常关键,因而所有 I/O 的主体实际上是内置在操作系统中的。...

    目录

     

    IO

    BIO

    NIO

    AIO

    区别及联系

    各自适用场景

    使用方式


    IO

    什么是IO? 它是指计算机与外部世界或者一个程序与计算机的其余部分的之间的接口。它对于任何计算机系统都非常关键,因而所有 I/O 的主体实际上是内置在操作系统中的。单独的程序一般是让系统为它们完成大部分的工作。

    在 Java 编程中,直到最近一直使用 流 的方式完成 I/O。所有 I/O 都被视为单个的字节的移动,通过一个称为 Stream 的对象一次移动一个字节。流 I/O 用于与外部世界接触。它也在内部使用,用于将对象转换为字节,然后再转换回对象。

    BIO

    Java BIO即Block I/O , 同步并阻塞的IO。

    BIO就是传统的java.io包下面的代码实现。

    NIO

    什么是NIO? NIO 与原来的 I/O 有同样的作用和目的, 他们之间最重要的区别是数据打包和传输的方式。原来的 I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。

    面向流 的 I/O 系统一次一个字节地处理数据。一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。为流式数据创建过滤器非常容易。链接几个过滤器,以便每个过滤器只负责单个复杂处理机制的一部分,这样也是相对简单的。不利的一面是,面向流的 I/O 通常相当慢。

    一个 面向块 的 I/O 系统以块的形式处理数据。每一个操作都在一步中产生或者消费一个数据块。按块处理数据比按(流式的)字节处理数据要快得多。但是面向块的 I/O 缺少一些面向流的 I/O 所具有的优雅性和简单性。

    AIO

    Java AIO即Async非阻塞,是异步非阻塞的IO。

    区别及联系

    BIO (Blocking I/O):同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。这里假设一个烧开水的场景,有一排水壶在烧开水,BIO的工作模式就是, 叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。但是实际上线程在等待水壶烧开的时间段什么都没有做。

    NIO (New I/O):同时支持阻塞与非阻塞模式,但这里我们以其同步非阻塞I/O模式来说明,那么什么叫做同步非阻塞?如果还拿烧开水来说,NIO的做法是叫一个线程不断的轮询每个水壶的状态,看看是否有水壶的状态发生了改变,从而进行下一步的操作。

    AIO ( Asynchronous I/O):异步非阻塞I/O模型。异步非阻塞与同步非阻塞的区别在哪里?异步非阻塞无需一个线程去轮询所有IO操作的状态改变,在相应的状态改变后,系统会通知对应的线程来处理。对应到烧开水中就是,为每个水壶上面装了一个开关,水烧开之后,水壶会自动通知我水烧开了。

    各自适用场景

    BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。

    NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。

    AIO方式适用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。

    使用方式

    使用BIO实现文件的读取和写入。

    
           //Initializes The Object
            User1 user = new User1();
            user.setName("hollis");
            user.setAge(23);
            System.out.println(user);
    
            //Write Obj to File
            ObjectOutputStream oos = null;
            try {
                oos = new ObjectOutputStream(new FileOutputStream("tempFile"));
                oos.writeObject(user);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                IOUtils.closeQuietly(oos);
            }
    
            //Read Obj from File
            File file = new File("tempFile");
            ObjectInputStream ois = null;
            try {
                ois = new ObjectInputStream(new FileInputStream(file));
                User1 newUser = (User1) ois.readObject();
                System.out.println(newUser);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } finally {
                IOUtils.closeQuietly(ois);
                try {
                    FileUtils.forceDelete(file);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
           //Initializes The Object
            User1 user = new User1();
            user.setName("hollis");
            user.setAge(23);
            System.out.println(user);
    
            //Write Obj to File
            ObjectOutputStream oos = null;
            try {
                oos = new ObjectOutputStream(new FileOutputStream("tempFile"));
                oos.writeObject(user);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                IOUtils.closeQuietly(oos);
            }
    
            //Read Obj from File
            File file = new File("tempFile");
            ObjectInputStream ois = null;
            try {
                ois = new ObjectInputStream(new FileInputStream(file));
                User1 newUser = (User1) ois.readObject();
                System.out.println(newUser);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } finally {
                IOUtils.closeQuietly(ois);
                try {
                    FileUtils.forceDelete(file);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
    

    使用NIO实现文件的读取和写入。

    
    static void readNIO() {
    		String pathname = "C:\\Users\\adew\\Desktop\\jd-gui.cfg";
    		FileInputStream fin = null;
    		try {
    			fin = new FileInputStream(new File(pathname));
    			FileChannel channel = fin.getChannel();
    
    			int capacity = 100;// 字节
    			ByteBuffer bf = ByteBuffer.allocate(capacity);
    			System.out.println("限制是:" + bf.limit() + "容量是:" + bf.capacity()
    					+ "位置是:" + bf.position());
    			int length = -1;
    
    			while ((length = channel.read(bf)) != -1) {
    
    				/*
    				 * 注意,读取后,将位置置为0,将limit置为容量, 以备下次读入到字节缓冲中,从0开始存储
    				 */
    				bf.clear();
    				byte[] bytes = bf.array();
    				System.out.write(bytes, 0, length);
    				System.out.println();
    
    				System.out.println("限制是:" + bf.limit() + "容量是:" + bf.capacity()
    						+ "位置是:" + bf.position());
    
    			}
    
    			channel.close();
    
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} finally {
    			if (fin != null) {
    				try {
    					fin.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    	}
    
    	static void writeNIO() {
    		String filename = "out.txt";
    		FileOutputStream fos = null;
    		try {
    
    			fos = new FileOutputStream(new File(filename));
    			FileChannel channel = fos.getChannel();
    			ByteBuffer src = Charset.forName("utf8").encode("你好你好你好你好你好");
    			// 字节缓冲的容量和limit会随着数据长度变化,不是固定不变的
    			System.out.println("初始化容量和limit:" + src.capacity() + ","
    					+ src.limit());
    			int length = 0;
    
    			while ((length = channel.write(src)) != 0) {
    				/*
    				 * 注意,这里不需要clear,将缓冲中的数据写入到通道中后 第二次接着上一次的顺序往下读
    				 */
    				System.out.println("写入长度:" + length);
    			}
    
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} finally {
    			if (fos != null) {
    				try {
    					fos.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    	}
    
    

    使用AIO实现文件的读取和写入

    public class ReadFromFile {
      public static void main(String[] args) throws Exception {
        Path file = Paths.get("/usr/a.txt");
        AsynchronousFileChannel channel = AsynchronousFileChannel.open(file);
    
        ByteBuffer buffer = ByteBuffer.allocate(100_000);
        Future<Integer> result = channel.read(buffer, 0);
    
        while (!result.isDone()) {
          ProfitCalculator.calculateTax();
        }
        Integer bytesRead = result.get();
        System.out.println("Bytes read [" + bytesRead + "]");
      }
    }
    class ProfitCalculator {
      public ProfitCalculator() {
      }
      public static void calculateTax() {
      }
    }
    
    public class WriteToFile {
    
      public static void main(String[] args) throws Exception {
        AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(
            Paths.get("/asynchronous.txt"), StandardOpenOption.READ,
            StandardOpenOption.WRITE, StandardOpenOption.CREATE);
        CompletionHandler<Integer, Object> handler = new CompletionHandler<Integer, Object>() {
    
          @Override
          public void completed(Integer result, Object attachment) {
            System.out.println("Attachment: " + attachment + " " + result
                + " bytes written");
            System.out.println("CompletionHandler Thread ID: "
                + Thread.currentThread().getId());
          }
    
          @Override
          public void failed(Throwable e, Object attachment) {
            System.err.println("Attachment: " + attachment + " failed with:");
            e.printStackTrace();
          }
        };
    
        System.out.println("Main Thread ID: " + Thread.currentThread().getId());
        fileChannel.write(ByteBuffer.wrap("Sample".getBytes()), 0, "First Write",
            handler);
        fileChannel.write(ByteBuffer.wrap("Box".getBytes()), 0, "Second Write",
            handler);
    
      }
    }
    展开全文
  • AIO 简介

    2019-05-12 00:11:54
    Linux的I/O机制经历了一下几个阶段的演进: 1. 同步阻塞I/O: 用户进程进行I/O操作,一直阻塞到I/O操作完成为止。 2. 同步非阻塞I/O: 用户程序可以通过设置文件描述符的属性O_NONBLOCK,I/O操作可以立即返回,但是...
  • linux下aio异步读写详解与实例

    千次阅读 2018-09-05 10:42:27
    aio异步读写是在linux内核2.6之后才正式纳入其标准。之所以会增加此模块,是因为众所周知我们计算机CPU的执行速度远大于I/O读写的执行速度,如果我们用传统的阻塞式或非阻塞式来操作I/O的话,那么我们在同一个程序中...
  • Linux下AIO服务设计框架

    千次阅读 2018-04-08 18:41:07
    对于异步I/O的概述aio异步读写是在Linux内核2.6之后才正式纳入其标准。之所以会增加此模块,是因为众所周知我们计算机CPU的执行速度远大于I/O读写的执行速度,如果我们用传统的阻塞式或非阻塞式来操作I/O的话,那么...
  • IO/NIO/AIO 基本概念

    千次阅读 2018-09-04 10:23:24
    1.阻塞IO—Socket Socket又称“套接字”,应用程序通常通过“套接字”向网络发出请求或应答网络请求。 Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。...
  • BIO,NIO,AIO的区别

    万次阅读 多人点赞 2018-03-18 13:16:40
    根据自己的理解,总结对比了一下BIO、NIO、AIO。BIO:线程发起IO请求,不管内核是否准备好IO操作,从发起请求起,线程一直阻塞,直到操作完成。如下图:NIO(reactor模型):线程发起IO请求,立即返回;内核在做好IO...
  • 无意中看到别人总结BIO-NIO-AIO-Netty的前世今生,也在往上翻阅了一些帖子,总感觉讲的太过于繁杂,往往一个简单的概念层层拓展,盖过了文章的主题,所以我想图文并茂的,层层递进,简单点、再简单点的讲出来。...
  • 本文会从传统的BIO到NIO再到AIO自浅至深介绍,并附上完整的代码讲解。 1、BIO编程 1.1、传统的BIO编程 网络编程的基本模型是C/S模型,即两个进程间的通信。 服务端提供IP和监听端口,客户端通过连接操作想服务端...
  • BIO与NIO、AIO的区别(这个容易理解)

    万次阅读 多人点赞 2016-10-20 15:52:50
    IO的方式通常分为几种,同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。 一、BIO  在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSocket,然后在客户端启动Socket...
  • JAVA BIO与NIO、AIO的区别(这个容易理解)

    万次阅读 多人点赞 2018-01-05 11:26:13
    IO的方式通常分为几种,同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。 一、BIO  在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSocket,然后在客户端启动Socket...
  • linux内核库aio

    千次阅读 2019-01-15 11:17:18
    linux内核库aio调研背景介绍两种头文件:5 个系统调用:(man手册)echo &amp;amp;amp;amp;amp;amp;gt; /proc/sys/fs/aio-max-nr 1048576 背景介绍 图 1. 基本 Linux I/O 模型的简单矩阵 两种头文件: ...
  • 聊聊BIO,NIO和AIO (2)

    千次阅读 2019-07-10 20:37:50
    本文从操作系统的角度来解释BIO,NIO,AIO的概念,含义和背后的那些事。本文主要分为3篇。 第一篇讲解BIO和NIO以及IO多路复用 第二篇讲解磁盘IO和AIO 第三篇 讲解在这些机制上的一些应用的实现方式,比如nginx,...
  • linux IO模型与AIO

    千次阅读 2016-12-15 12:49:29
    AIO 简介 Linux 异步 I/O 是 Linux 内核中提供的一个相当新的增强。它是 2.6 版本内核的一个标准特性,但是我们在 2.4 版本内核的补丁中也可以找到它。AIO 背后的基本思想是允许进程发起很多 I/O 操作,而不用阻塞...
  • BIO、NIO、AIO 有什么区别?

    万次阅读 多人点赞 2020-02-04 16:15:07
    BIO、NIO、AIO 有什么区别? BIO:线程发起IO请求,不管内核是否准备好IO操作,从发起请求起,线程一直阻塞,直到操作完成。 NIO:线程发起IO请求,立即返回;内核在做好IO操作的准备之后,通过调用注册的回调...
  • java中的AIO

    千次阅读 2018-07-15 09:35:37
    转载自 java中的AIO简介jdk7中新增了一些与文件(网络)I/O相关的一些api。这些API被称为NIO.2,或称为AIO(Asynchronous I/O)。AIO最大的一个特性就是异步能力,这种能力对socket与文件I/O都起作用。AIO其实是一种...
  • AIO用于文件处理还是比较快乐的,但用AIO来写网络消息处理服务器端与客户端是比较麻烦的事情,当然这只是我个人意见,主要是有几点原因: 一是AIO需要操作系统支持,还好Windows与Linux(模拟)都支持; 二是AIO同时...
1 2 3 4 5 ... 20
收藏数 44,485
精华内容 17,794
关键字:

aio