Java 8 native API can also develop responsive Code?

asphalt-automobile-automotive-1172105.jpg

Some time ago a busy work, has not had time to write this article, this article is read "Java8 combat" when learned Java 8 already provides a non-blocking asynchronous interface (CompletableFuture), you can achieve a simple reactive programming mode, so use this article to be combed. I took the following questions to learn CompletableFuture this interface,

  1. CompletableFuture to solve the problem and design?
  2. What is its use scene? There are practical open source software use cases do?
  3. CompletableFuture common API what are? how to use?
  4. CompletableFuture and RxJava What is the difference?

This article comb down, basically can answer the first four questions, OK, we enter the text.

basic concept

Pictures taken from Dubbo official blog
RPC (Remote Method Invocation) four methods are: oneway, sync, future callback and, in dubbo bolt or such communication frame, the default sync mode (synchronization + obstruction), and Future callback belong to the asynchronous mode, but future models will get blocked at the time of, callback mode you do not need to wait for the results, the server calls back after the outcome of the requesting party.

Such asynchronous call mode, the scene is more suitable for IO-intensive scenes, to perform many tasks remote call, and these calls may be more time-consuming for a long time. With a case openwrite as an example: I published an article, you need to create a platform for several different writing articles, this time I do not want this process is sequential, it is more suitable for asynchronous invocation patterns.

Future mode except when get () call will block, there are other limitations, such as: do not use the advantages of Java Lambda expressions, can support a series of asynchronous calls, but to write out the code would be more complex.

CompletableFuture common API

Read CompletableFuture the API, I have come to realize --CompletableFuture is to the Future, in addition to increasing the pullback this most important characteristics, other features for enhancing Stream bit like a set of iterations.

使用CompletableFuture,我们可以像Stream一样使用一部调用,可以处理一些级联的异步调用(类似于Stream里的flatMap)、可以过滤一些无用的异步调用(anyOf、allOf)。

下面这张图是我按照自己的理解,梳理除了CompletableFuture常见的API,阅读的时候需要注意下面几个点:

  1. 把握几个大的分类:创建CompletableFuture、获取CompletableFuture的执行结果、主动结束CompletableFuture、异步调用任务的组合处理;
  2. 看着方法多,但是有规律可循,例如apply字样的接口,传入的方法参数都是有返回值的;
  3. 带either字样的,都是多个异步任务有一个满足条件即可的;
  4. 带executor方法的,都表示该方法可以用自定义的线程池来优化性能。

CompletableFuture的API

Dubbo项目中的使用案例

Dubbo对于异步化的支持起始在2.6.x中就有提供,是在发布bean的时候加个属性配置——async=true,然后利用上下文将异步标识一层层传递下去。在之前的公司中有一次排查dubbo(当时我们用的是dubbox)异步调用的问题,最后查到的原因就是多个异步调用,上下文里的信息串了。

Dubbo 2.7 中使用了 JDK1.8 提供的 CompletableFuture 原生接口对自身的异步化做了改进。CompletableFuture 可以支持 future 和 callback 两种调用方式。在Dubbo最新的master代码中,我知道了Dubbo的异步结果的定义,它的类图如下,可以看出AsyncRpcResult是一个CompletableFuture接口的实现。

AsyncRpcResult.png

实战Demo

通过下面的例子,可以看出CompletableFuture的最大好处——callback特性。首先定义一个接口,其中包括同步接口和该接口的异步版本。

public interface AsyncInterfaceExample {

    String computeSomeThine();

    CompletableFuture<String> computeSomeThingAsync();
}

然后定义该接口的实现类,可以看出,如果要讲现有的同步接口异步化,是比较容易的;

public class AsyncInterfaceExampleImpl implements AsyncInterfaceExample {

    @Override
    public String computeSomeThine() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return "hello, world";
    }

    @Override
    public CompletableFuture<String> computeSomeThingAsync() {
        return CompletableFuture.supplyAsync(this::computeSomeThine);
    }
}

然后看下我们的测试case,如下:

public class AsyncInterfaceExampleTest {

    private static String getOtherThing() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return "other";
    }

    public static void main(String[] args) {
        AsyncInterfaceExample asyncInterfaceExample = new AsyncInterfaceExampleImpl();

        //case1 同步调用
        long start = System.currentTimeMillis();
        String someThing = asyncInterfaceExample.computeSomeThine();
        String other = getOtherThing();
        System.out.println("cost:" + (System.currentTimeMillis() - start) + "  result:" + someThing + other);

        //case2 异步调用,使用回调
        start = System.currentTimeMillis();
        CompletableFuture<String> someThingFuture = asyncInterfaceExample.computeSomeThingAsync();
        other = getOtherThing();

        long finalStart = start;
        String finalOther = other;
        someThingFuture.whenComplete((returnValue, exception) -> {
            if (exception == null) {
                System.out.println(
                    "cost:" + (System.currentTimeMillis() - finalStart) + "  result:" + returnValue + finalOther);
            } else {
                exception.printStackTrace();
            }
        });
    }
}

The above results of the implementation of this case, as shown below:
Results of the***
This number (javaadu) focused on the back-end technology, JVM troubleshooting and optimization, Java interview questions, personal growth and self-management, and other topics, to provide readers with first-line developers work experience and growth, you can expect to gain something here.

Guess you like

Origin www.cnblogs.com/javaadu/p/11333246.html