zoukankan      html  css  js  c++  java
  • Java 异步 IO

      新的异步功能的关键点,它们是Channel 类的一些子集,Channel 在处理IO操作的时候需要被切换成一个后台进程。一些需要访问较大,耗时的操作,或是其它的类似实例,可以考虑应用此功能。
    在这里,我们只单独讲解针对文件IO操作的 AsynchronousFileChannel,但是需要注意的是,还有一些其他的异步管道。这里包括:

    • AsynchronousFileChannel:针对文件;
    • AsynchronousSocketChannel :针对客户端的socket;
    • AsynchronousServerSocketChannel:针对服务器端的异步socket,用来接收到来的连接。

    针对异步管道的交互有两种不同的方式,

    1. Future 风格;
    2. callback 风格。

    Future 风格的异步操作

    这里需要使用Future 接口, 它可以被认为是一个正在进行的任务,也可能是尚未完成的任务。它有两个关键的方法:

    isDone()
      返回一个布尔值来表示任务是否已经完成。
    get()
      返回结果。如果任务完成,立即返回。否则,一直堵塞,直到完成。
    让我们看段关于读取一个内容比较大的文件,或许超过100M的一个异步操作:

        try(AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get("input.txt"))) {
                ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 1024 * 100);
                Future<Integer> result = channel.read(buffer, 0);
                
                while(!result.isDone()) {
                    // do some other useful work
                    System.out.println("reading file, I can do other work.");
                }
                 System.out.println("Bytes read: " + result.get());
            } catch (IOException | InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }

    callback 风格的异步操作

      基于callback风格的异步操作需要 CompletionHandler的帮忙,它定义了两个方法, completed() 和failed(),分别用来表示在回调结束后是否完成和失败。
    这种风格特别适用于,你想在异步IO操作中立即知道事件的通知。例如,如果在云中有大量的I O操作,但任何单一操作的失败不一定是致命的。看例子。

            byte[] data = { 2, 3, 5, 7, 11, 13, 17, 19, 23 };
            ByteBuffer buffer = ByteBuffer.wrap(data);
    
            CompletionHandler<Integer, Object> handler = new CompletionHandler<Integer, Object>() {
                @Override
                public void completed(Integer result, Object attachment) { // success
                    System.out.println("Bytes written: " + result);
                }
    
                @Override
                public void failed(Throwable exc, Object attachment) { // failed
                    System.out.println("Asynch write failed: " + exc.getMessage());
                }
            };
    
            try (AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get("primes.txt"),
                    StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
    
                channel.write(buffer, 0, null, handler);
                
                Thread.sleep(10000); // Needed so we don't exit too quickly
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }        

      AsynchronousFileChannel 与后台线程池相连接,所以当初始线程处理其他任务的时候,以至于IO操作能够得以进行。
    默认情况下,这种情况实际是管理一个运行时环境提供了的线程池,如果有需要,可以通过应用程序(通过重载 AsynchronousFileChannel.open()方法)创建一个自定义的线程池,不过这种情况通常不是必要的。
      另外,在nio 中还支持多重IO,这样就可以使一个单线程管理多个IO管道和检查它的哪些IO管道是否做好了读取和写入的准备,支持此操作的一些类在 java.nio.channels包下,包括 SelectableChannel 和 Selector。

  • 相关阅读:
    USACO Milk2 区间合并
    Codeforces 490B Queue【模拟】
    HDU 3974 Assign the task 简单搜索
    HDU 5119 Happy Matt Friends(2014北京区域赛现场赛H题 裸背包DP)
    Cin、Cout 加快效率方法
    POJ 1159 回文LCS滚动数组优化
    POJ 2479 不相交最大子段和
    POJ 1458 最长公共子序列 LCS
    在阿里最深刻的,还是职场之道给我的震撼
    精细化
  • 原文地址:https://www.cnblogs.com/IcanFixIt/p/6366264.html
Copyright © 2011-2022 走看看