欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识
原文出处: 鸟窝

在Java中异步编程,不必然非要利用rxJava, Java自己的库中的CompletableFuture可以很好的应对大部门的场景。

原文: 20 Examples of Using Java’s CompletableFuture, 作者 Mahmoud Anouti。

这篇文章先容 Java 8 的 CompletionStage API和它的尺度库的实现 CompletableFuture。API通过例子的方法演示了它的行为,每个例子演示一到两个行为。

既然CompletableFuture类实现了CompletionStage接口,首先我们需要领略这个接口的契约。它代表了一个特定的计较的阶段,可以同步可能异步的被完成。你可以把它当作一个计较流水线上的一个单位,最终会发生一个最终功效,这意味着几个CompletionStage可以串联起来,昆山软件开发,一个完成的阶段可以触发下一阶段的执行,接着触发下一次,接着……

除了实现CompletionStage接口, CompletableFuture也实现了future接口, 代表一个未完成的异步事件。CompletableFuture提供了要领,可以或许显式地完成这个future,所以它叫CompletableFuture

1、 建设一个完成的CompletableFuture

最简朴的例子就是利用一个预界说的功效建设一个完成的CompletableFuture,凡是我们会在计较的开始阶段利用它。

static void completedFutureExample() {
    CompletableFuture cf = CompletableFuture.completedFuture("message");
    assertTrue(cf.isDone());
    assertEquals("message", cf.getNow(null));
}

getNow(null)要领在future完成的环境下会返回功效,就好比上面这个例子,不然返回null (传入的参数)。

2、运行一个简朴的异步阶段

这个例子建设一个一个异步执行的阶段:

static void runAsyncExample() {
    CompletableFuture cf = CompletableFuture.runAsync(() -> {
        assertTrue(Thread.currentThread().isDaemon());
        randomSleep();
    });
    assertFalse(cf.isDone());
    sleepEnough();
    assertTrue(cf.isDone());
}

通过这个例子可以学到两件工作:

CompletableFuture的要领假如以Async末了,它会异步的执行(没有指定executor的环境下), 异步执行通过ForkJoinPool实现, 它利用守护线程去执行任务。留意这是CompletableFuture的特性, 其它CompletionStage可以override这个默认的行为。

3、在前一个阶段上应用函数

下面这个例子利用前面 #1 的完成的CompletableFuture, #1返回功效为字符串message,然后应用一个函数把它酿成大写字母。

static void thenApplyExample() {
    CompletableFuture cf = CompletableFuture.completedFuture("message").thenApply(s -> {
        assertFalse(Thread.currentThread().isDaemon());
        return s.toUpperCase();
    });
    assertEquals("MESSAGE", cf.getNow(null));
}

留意thenApply要领名称代表的行为。

then意味着这个阶段的行动产生当前的阶段正常完成之后。本例中,当前节点完成,返回字符串message

Apply意味着返回的阶段将会对功效前一阶段的功效应用一个函数。

函数的执行会被阻塞,这意味着getNow()只有打斜操纵被完成后才返回。

4、在前一个阶段上异步应用函数

通过挪用异步要领(要领后边加Async后缀),串联起来的CompletableFuture可以异步地执行(利用ForkJoinPool.commonPool())。

static void thenApplyAsyncExample() {
    CompletableFuture cf = CompletableFuture.completedFuture("message").thenApplyAsync(s -> {
        assertTrue(Thread.currentThread().isDaemon());
        randomSleep();
        return s.toUpperCase();
    });
    assertNull(cf.getNow(null));
    assertEquals("MESSAGE", cf.join());
}

5、利用定制的Executor在前一个阶段上异步应用函数

异步要领一个很是有用的特性就是可以或许提供一个Executor来异步地执行CompletableFuture。这个例子演示了如何利用一个牢靠巨细的线程池来应用大写函数。

static ExecutorService executor = Executors.newFixedThreadPool(3, new ThreadFactory() {
    int count = 1;
 
    @Override
    public Thread newThread(Runnable runnable) {
        return new Thread(runnable, "custom-executor-" + count++);
    }
});
 
static void thenApplyAsyncWithExecutorExample() {
    CompletableFuture cf = CompletableFuture.completedFuture("message").thenApplyAsync(s -> {
        assertTrue(Thread.currentThread().getName().startsWith("custom-executor-"));
        assertFalse(Thread.currentThread().isDaemon());
        randomSleep();
        return s.toUpperCase();
    }, executor);
 
    assertNull(cf.getNow(null));
    assertEquals("MESSAGE", cf.join());
}

6、消费前一阶段的功效