“CompletionHandler”和“CompletableFuture”是Java中异步编程的两种不同方法吗?

时间:2017-10-18 16:40:12

标签: java asynchronous callback future

Java in a Nutshell

  

异步I / O的回调样式基于 CompletionHandler ,   定义了两个方法completed()failed(),它们将在回调时被回调   操作成功或失败。   如果要在异步中立即通知事件,则此样式很有用   I / O-例如,如果飞行中有大量I / O操作,但是失败   任何单一操作都不一定是致命的。

来自http://www.deadcoderising.com/java8-writing-asynchronous-code-with-completablefuture/

  

除了实施Future界面之外,还CompletableFuture   实现CompletionStage接口。

     

CompletionStage是一个承诺。它承诺计算   最终将完成。

     

CompletionStage的伟大之处在于它提供了广阔的空间   选择允许您附加回调的方法   在完成时执行。

     

这样我们就可以以非阻塞的方式构建系统。

CompletionHandlerCompletableFuture都可用于指定回调处理程序。

他们的关系和差异是什么?

CompletionHandlerCompletableFuture两种不同的Java异步编程方法吗?

或者它们是否一起使用?

感谢。

2 个答案:

答案 0 :(得分:2)

CompletionHandler<V, A>是NIO异步通道的完成界面。

它是在Java 7中引入的,几年前Java 8引入了lambda表达式并将它们转换为功能接口(使用单个抽象方法的接口),因此它有两个方法,completed(V result, A attachment)和{{1} },而不是(现在)更舒适的单一方法。

failed(Throwable ex, A attachment)CompletableFuture<T>接口的实现。

它是在Java 8中引入的,因此构建future的静态方法及其构建continuation的实例方法使用功能接口,您可以使用它们轻松使用lambda表达式。

您可以包装每个NIO异步调用以使用CompletionStage<T>

CompletableFuture<T>

示例用法(仅用于说明;没有错误处理,不处理资源):

import java.lang.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*;
import java.util.concurrent.*;

public class AsynchronousCompletionHandler<T> implements CompletionHandler<T, CompletableFuture<T>> {
    public void completed(T result, CompletableFuture<T> attachment) {
        attachment.complete(result);
    }

    public void failed(Throwable ex, CompletableFuture<T> attachment) {
        attachment.completeExceptionally(ex);
    }

    private static final ConcurrentHashMap<Class<?>, AsynchronousCompletionHandler<?>> cache = new ConcurrentHashMap<>();

    static <T> AsynchronousCompletionHandler<T> getInstance(Class<T> clazz) {
        @SuppressWarnings("unchecked")
        AsynchronousCompletionHandler<T> handler = (AsynchronousCompletionHandler<T>)cache.computeIfAbsent(clazz, c -> new AsynchronousCompletionHandler<T>());
        return handler;
    }

    //
    // AsynchronousByteChannel
    public static CompletableFuture<Integer> readAsync(AsynchronousByteChannel channel, ByteBuffer dst) {
        CompletableFuture<Integer> completableFuture = new CompletableFuture<>();
        channel.read(dst, completableFuture, getInstance(Integer.class));
        return completableFuture;
    }

    public static CompletableFuture<Integer> writeAsync(AsynchronousByteChannel channel, ByteBuffer src) {
        CompletableFuture<Integer> completableFuture = new CompletableFuture<>();
        channel.write(src, completableFuture, getInstance(Integer.class));
        return completableFuture;
    }

    //
    // AsynchronousFileChannel
    public static CompletableFuture<FileLock> lockAsync(AsynchronousFileChannel channel) {
        CompletableFuture<FileLock> completableFuture = new CompletableFuture<>();
        channel.lock(completableFuture, getInstance(FileLock.class));
        return completableFuture;
    }

    public static CompletableFuture<FileLock> lockAsync(AsynchronousFileChannel channel, long position, long size, boolean shared) {
        CompletableFuture<FileLock> completableFuture = new CompletableFuture<>();
        channel.lock(position, size, shared, completableFuture, getInstance(FileLock.class));
        return completableFuture;
    }

    public static CompletableFuture<Integer> readAsync(AsynchronousFileChannel channel, ByteBuffer dst, long position) {
        CompletableFuture<Integer> completableFuture = new CompletableFuture<>();
        channel.read(dst, position, completableFuture, getInstance(Integer.class));
        return completableFuture;
    }

    public static CompletableFuture<Integer> writeAsync(AsynchronousFileChannel channel, ByteBuffer src, long position) {
        CompletableFuture<Integer> completableFuture = new CompletableFuture<>();
        channel.write(src, position, completableFuture, getInstance(Integer.class));
        return completableFuture;
    }

    //
    // AsynchronousServerSocketChannel
    public static CompletableFuture<AsynchronousSocketChannel> acceptAsync(AsynchronousServerSocketChannel channel) {
        CompletableFuture<AsynchronousSocketChannel> completableFuture = new CompletableFuture<>();
        channel.accept(completableFuture, getInstance(AsynchronousSocketChannel.class));
        return completableFuture;
    }

    //
    // AsynchronousSocketChannel
    public static CompletableFuture<Void> connectAsync(AsynchronousSocketChannel channel, SocketAddress remote) {
        CompletableFuture<Void> completableFuture = new CompletableFuture<>();
        channel.connect(remote, completableFuture, getInstance(Void.class));
        return completableFuture;
    }

    public static CompletableFuture<Long> readAsync(AsynchronousSocketChannel channel, ByteBuffer[] dsts, int offset, int length, long timeout, TimeUnit unit) {
        CompletableFuture<Long> completableFuture = new CompletableFuture<>();
        channel.read(dsts, offset, length, timeout, unit, completableFuture, getInstance(Long.class));
        return completableFuture;
    }

    public static CompletableFuture<Integer> readAsync(AsynchronousSocketChannel channel, ByteBuffer dst) {
        CompletableFuture<Integer> completableFuture = new CompletableFuture<>();
        channel.read(dst, completableFuture, getInstance(Integer.class));
        return completableFuture;
    } 

    public static CompletableFuture<Integer> readAsync(AsynchronousSocketChannel channel, ByteBuffer dst, long timeout, TimeUnit unit) {
        CompletableFuture<Integer> completableFuture = new CompletableFuture<>();
        channel.read(dst, timeout, unit, completableFuture, getInstance(Integer.class));
        return completableFuture;
    }

    public static CompletableFuture<Long> writeAsync(AsynchronousSocketChannel channel, ByteBuffer[] srcs, int offset, int length, long timeout, TimeUnit unit) {
        CompletableFuture<Long> completableFuture = new CompletableFuture<>();
        channel.write(srcs, offset, length, timeout, unit, completableFuture, getInstance(Long.class));
        return completableFuture;
    }

    public static CompletableFuture<Integer> writeAsync(AsynchronousSocketChannel channel, ByteBuffer src) {
        CompletableFuture<Integer> completableFuture = new CompletableFuture<>();
        channel.write(src, completableFuture, getInstance(Integer.class));
        return completableFuture;
    } 

    public static CompletableFuture<Integer> writeAsync(AsynchronousSocketChannel channel, ByteBuffer src, long timeout, TimeUnit unit) {
        CompletableFuture<Integer> completableFuture = new CompletableFuture<>();
        channel.write(src, timeout, unit, completableFuture, getInstance(Integer.class));
        return completableFuture;
    }
}

答案 1 :(得分:1)

如果你看一下CompletableFuture(自Java 8以来),你会发现它拥有大量的功能,不仅仅是回调。具有链接,组合和其他有趣的功能。

将其与CompletionHandler(自Java 7以来)进行比较,差异应该是显而易见的。

没有什么可以阻止您同时使用这两种方式,甚至可能根据您使用的API类型进行操作,但如果您有机会使用CompletableFuture,那么您真的不会这样做。需要加强CompletionHandler