美文网首页
Java基础-AIO

Java基础-AIO

作者: 16325 | 来源:发表于2020-02-24 17:48 被阅读0次

    AIO

    More New IO,或称 NIO.2,随 JDK 1.7 发布,包括了引入异步 IO 接口和 Paths 等文件访问接口。

    异步这个词,我想对于绝大多数开发者来说都很熟悉,很多场景下我们都会使用异步。

    通常,我们会有一个线程池用于执行异步任务,提交任务的线程将任务提交到线程池就可以立马返回,不必等到任务真正完成。如果想要知道任务的执行结果,通常是通过传递一个回调函数的方式,任务结束后去调用这个函数。

    同样的原理,Java 中的异步 IO 也是一样的,都是由一个线程池来负责执行任务,然后使用回调或自己去查询结果。

    大部分开发者都知道为什么要这么设计了,这里再啰嗦一下。异步 IO 主要是为了控制线程数量,减少过多的线程带来的内存消耗和 CPU 在线程调度上的开销。

    在 Unix/Linux 等系统中,JDK 使用了并发包中的线程池来管理任务,具体可以查看 AsynchronousChannelGroup 的源码。

    在 Windows 操作系统中,提供了一个叫做 I/O Completion Ports 的方案,通常简称为 IOCP,操作系统负责管理线程池,其性能非常优异,所以在 Windows 中 JDK 直接采用了 IOCP 的支持,使用系统支持,把更多的操作信息暴露给操作系统,也使得操作系统能够对我们的 IO 进行一定程度的优化。

    • AsynchronousSocketChannel
    • AsynchronousServerSocketChannel
    • AsynchronousFileChannel
      这三个类对应的NIO中SocketChannel, ServerSocketChannel,FileChannel

    Java 异步 IO 提供了两种使用方式,分别是返回 Future 实例和使用回调函数。

    • 返回 Future 实例
      没错,就是java.util.concurrent.Future 实例
    • 提供 CompletionHandler 回调函数
    public interface CompletionHandler<V,A> {
        void completed(V result, A attachment);
        void failed(Throwable exc, A attachment);
    }
    

    AsynchronousFileChannel

    • 实例化:

    AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get("/Users/hongjie/test.txt"));

    • 读入到 Buffer 中:

    ByteBuffer buffer = ByteBuffer.allocate(1024);
    Future<Integer> result = channel.read(buffer, 0);

    • 除了使用返回 Future 实例的方式,也可以采用回调函数:

    public abstract <A> void read(ByteBuffer dst,long position, A attachment,CompletionHandler<Integer,? super A> handler);

    AsynchronousServerSocketChannel

    非阻塞 IO 的 ServerSocketChannel

    AsynchronousSocketChannel

    Asynchronous Channel Groups

    为了知识的完整性,有必要对 group 进行介绍,其实也就是介绍 AsynchronousChannelGroup 这个类。之前我们说过,异步 IO 一定存在一个线程池,这个线程池负责接收任务、处理 IO 事件、回调等。这个线程池就在 group 内部,group 一旦关闭,那么相应的线程池就会关闭。

    • AsynchronousServerSocketChannels 和 AsynchronousSocketChannels 是属于 group 的,当我们调用 AsynchronousServerSocketChannel 或 AsynchronousSocketChannel 的 open() 方法的时候,相应的 channel 就属于默认的 group,这个 group 由 JVM 自动构造并管理。
    • 如果我们想要配置这个默认的 group,可以在 JVM 启动参数中指定以下系统变量:

    java.nio.channels.DefaultThreadPool.threadFactory
    此系统变量用于设置 ThreadFactory,它应该是 java.util.concurrent.ThreadFactory 实现类的全限定类名。一旦我们指定了这个 ThreadFactory 以后,group 中的线程就会使用该类产生。

    java.nio.channels.DefaultThreadPool.initialSize
    此系统变量也很好理解,用于设置线程池的初始大小。

    • 可能你会想要使用自己定义的 group,这样可以对其中的线程进行更多的控制,使用以下几个方法即可:
      1 AsynchronousChannelGroup.withCachedThreadPool(ExecutorService executor, int initialSize)
      2 AsynchronousChannelGroup.withFixedThreadPool(int nThreads, ThreadFactory threadFactory)
      3 AsynchronousChannelGroup.withThreadPool(ExecutorService executor)

    • 至于 group 的使用:

    AsynchronousChannelGroup group = AsynchronousChannelGroup
            .withFixedThreadPool(10, Executors.defaultThreadFactory());
    AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open(group);
    AsynchronousSocketChannel client = AsynchronousSocketChannel.open(group);
    

    小结

    • •BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。
    • •NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。
    • •AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。​​

    相关文章

      网友评论

          本文标题:Java基础-AIO

          本文链接:https://www.haomeiwen.com/subject/boivqhtx.html