1.CompletableFuture的方法简介和使用

2.总结

1.CompletableFuture的方法简介和使用
从上面那篇博客 JAVA并发编程——Future和CompletableFuture的简介与使用 我们对CompletableFuture有了一个大概的了解和初步的使用,接下来我们来系统介绍一下CompletableFuture这个类有哪些方法。

1.0 基础的运行方法

//无返回值,类似Runnable 可选择传入一个线程池
public static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor)
 //有返回值,类似Future 可选择传入一个线程池
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor)

1.1 获得结果和触发计算的方法

public T    get();//一直阻塞获取结果,和Future的get()方法相同
public T    get(long timeout, TimeUnit unit);// 在一定时间内获取结果,没获得结果就抛异常
public T    getNow(T valueIfAbsent);//马上获取结果,如果没获取到结果就返回传入参数的默认值。
public T    join(); //和get()方法相同,区别是join()不会抛出异常,get()会抛出异常
public boolean complete(T value) //在计算未完成的情况下,立刻打断get方法立即返回括号值

1.2 对计算结果进行处理的方法

thenApply() 
//计算结果存在依赖关系,先执行上一步再执行下一步
//由于存在依赖关系(当前步错,不走下一步),当前步骤有异常的话就叫停。
public class CompletableFutureDemo2
{
public static void main(String[] args) throws ExecutionException, InterruptedException
{
//当一个线程依赖另一个线程时用 thenApply 方法来把这两个线程串行化,
CompletableFuture.supplyAsync(() -> {
//暂停几秒钟线程
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
        System.out.println("111");
return 1024;
    }).thenApply(f -> {
        System.out.println("222");
return f + 1;
    }).thenApply(f -> {
//int age = 10/0; // 异常情况:那步出错就停在那步。
System.out.println("333");
return f + 1;
    }).whenCompleteAsync((v,e) -> {//当完成的时候
        System.out.println("*****v: "+v);
    }).exceptionally(e -> {//当发生异常的时候
        e.printStackTrace();
return null;
    });

    System.out.println("-----主线程结束,END");

// 主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭:
try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
}

}

//有异常也可以往下一步走,根据带的异常参数可以进一步处理
handle()
public class CompletableFutureDemo2
{

public static void main(String[] args) throws ExecutionException, InterruptedException
    {
//当一个线程依赖另一个线程时用 handle 方法来把这两个线程串行化,
        // 异常情况:有异常也可以往下一步走,根据带的异常参数可以进一步处理
CompletableFuture.supplyAsync(() -> {
//暂停几秒钟线程
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
            System.out.println("111");
return 1024;
        }).handle((f,e) -> {
int age = 10/0;
            System.out.println("222");
return f + 1;
        }).handle((f,e) -> {
            System.out.println("333");
return f + 1;
        }).whenCompleteAsync((v,e) -> {
            System.out.println("*****v: "+v);
        }).exceptionally(e -> {
            e.printStackTrace();
return null;
        });

        System.out.println("-----主线程结束,END");

// 主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭:
try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
    }


}

1.3 对计算结果进行消费的方法

//接收任务的处理结果,并消费处理,无返回结果
thenAccept();
//任务 A 执行完执行 B,并且 B 不需要 A 的结果
thenRun();
//任务 A 执行完执行 B,B 需要 A 的结果,但是任务 B 无返回值
thenAccept();
//任务 A 执行完执行 B,B 需要 A 的结果,同时任务 B 有返回值
thenApply();
public static void main(String[] args) throws ExecutionException, InterruptedException
{
    CompletableFuture.supplyAsync(() -> {
return 1;
    }).thenApply(f -> {
return f + 2;
    }).thenApply(f -> {
return f + 3;
    }).thenApply(f -> {
return f + 4;
    }).thenAccept(r -> System.out.println(r));
}

1.4 对计算速度进行选用的方法

//谁快用谁
applyToEither()
public class CompletableFutureDemo2
{
public static void main(String[] args) throws ExecutionException, InterruptedException
    {
        CompletableFuture completableFuture1 = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "---come in ");
//暂停几秒钟线程
try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
return 10;
        });

        CompletableFuture completableFuture2 = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "---come in ");
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
return 20;
        });

        CompletableFuture thenCombineResult = completableFuture1.applyToEither(completableFuture2,f -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "---come in ");
return f + 1;
        });

        System.out.println(Thread.currentThread().getName() + "\t" + thenCombineResult.get());
    }
}

1.5 对计算结果进行合并的方法

//两个CompletionStage任务都完成后,最终能把两个任务的结果一起交给thenCombine 来处理
thenCombine()
public class CompletableFutureDemo2
{
public static void main(String[] args) throws ExecutionException, InterruptedException
    {
        CompletableFuture completableFuture1 = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "---come in ");
return 10;
        });

        CompletableFuture completableFuture2 = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "---come in ");
return 20;
        });

        CompletableFuture thenCombineResult = completableFuture1.thenCombine(completableFuture2, (x, y) -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "---come in ");
return x + y;
        });

        System.out.println(thenCombineResult.get());
    }
}

2.总结

这篇博客我们总结了CompletableFuture的基础方法,我们还是需要在生产上多加练习,忘记api的时候可以看一下源码或者重新翻阅一下这篇博客。


苏凌峰
73 声望38 粉丝

你的迷惑在于想得太多而书读的太少。