Java Future与CompletableFuture的用法、区别

Future的用法
多线程场景时,一般是实现runnable接口,覆写run方法,返回值是void类型,因此这种情况下不需要线程的返回结果。 
如果需要线程的返回结果,就需要用callable接口来代替了。 
callable用法和runnable一样,只不过覆写的是call方法,该方法有一个泛型返回值类型,可以根据需要指定。 
那么何时到Future呢?当你启动callable线程时,就可以声明一个Future对象,用于接收返回结果。
Futrue可以监视目标线程调用call的情况,当你调用Future的get()方法以获得结果时,调用方的线程就被阻塞,直到目标线程的call方法结束并返回结果。
Future接口,一般都是取回Callable执行的状态用的。其中的主要方法:

cancel,取消Callable的执行,当Callable还没有完成时
get,获得Callable的返回值
isCanceled,判断是否取消了
isDone,判断是否完成
举个栗子。
四个刚需(线程)去买房摇号,future获取摇号结果。摇号结果未出,就一直阻塞。

public class FutureTest {
 
    /**
     * 买房摇号
     */
    public static class Yaohao implements Callable<Integer> {
        /**
         * 返回摇号结果
         * @return 0:中签   1:没中
         * @throws Exception
         */
        @Override
        public Integer call() throws Exception {
            Random random = new Random();
            //模拟摇号,10天内出结果
            TimeUnit.SECONDS.sleep(random.nextInt(10));
            int result = random.nextInt(2);
            System.out.println("     "+Thread.currentThread().getName()+" is done!");
            return result;
        }
    }
 
    public static void main(String[] args) throws InterruptedException, ExecutionException {
 
        Yaohao gangxu1 = new Yaohao();
        Yaohao gangxu2 = new Yaohao();
        ExecutorService es = Executors.newCachedThreadPool();
        Future<Integer> result1 = es.submit(gangxu1);
        Future<Integer> result2 = es.submit(gangxu2);
        es.shutdown();
 
        System.out.println("刚需1,摇号结果:"+(result1.get()==1?"中签":"没中"));
        System.out.println("刚需2,摇号结果:"+(result2.get()==1?"中签":"没中"));
    }
 
}
CompletableFuture的用法
 创建异步操作,runAsync(不支持返回值) 和 supplyAsync方法(支持返回值)
计算结果完成时的回调方法
   whenComplete:执行完当前任务的线程,继续执行 whenComplete 的任务。
   whenCompleteAsync: 执行完当前任务的线程,把whenCompleteAsync 的任务继续提交给线程池来执行。
   exceptionally:当前任务出现异常时,执行exceptionally中的回调方法。
thenApply 方法,当一个线程依赖另一个线程时,可以使用 thenApply 方法来把这两个线程串行化。
handle 方法
handle 是执行任务完成时对结果的处理。
handle 方法和 thenApply 方法处理方式基本一样。不同的是 handle 是在任务完成后再执行,还可以处理异常的任务。thenApply 只可以执行正常的任务,任务出现异常则不执行 thenApply 方法。
thenAccept 消费处理结果,接收任务的处理结果,并消费处理,无返回结果。
thenRun 方法,跟 thenAccept 方法不一样的是,不关心任务的处理结果。只要上面的任务执行完成,就开始执行 thenAccept 。
thenCombine 合并任务,thenCombine 会把 两个 CompletionStage 的任务都执行完成后,把两个任务的结果一块交给 thenCombine 来处理。
thenCompose 方法,thenCompose 方法允许你对两个 CompletionStage 进行流水线操作,第一个操作完成时,将其结果作为参数传递给第二个操作。
案例:

1、 runAsync 和 supplyAsync方法

CompletableFuture 提供了四个静态方法来创建一个异步操作。

public static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)

没有指定Executor的方法会使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码。如果指定线程池,则使用指定的线程池运行。以下所有的方法都类同。

  • runAsync方法不支持返回值。
  • supplyAsync可以支持返回值。

示例

//无返回值
public static void runAsync() throws Exception {
    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
        }
        System.out.println("run end ...");
    });
    
    future.get();
}

//有返回值
public static void supplyAsync() throws Exception {         
    CompletableFuture<Long> future = CompletableFuture.supplyAsync(() -> {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
        }
        System.out.println("run end ...");
        return System.currentTimeMillis();
    });

    long time = future.get();
    Syst
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值