首页 > 其他分享 >CompletableFuture

CompletableFuture

时间:2022-12-24 17:34:13浏览次数:33  
标签:Thread getName System 线程 println CompletableFuture out

Future

Future接口提供了异步并行计算的功能,可以为主线程开一个分支任务,专门为主线程处理耗时和费力的复杂任务。

(FutureTask)实现类满足三个特点,1,多线程    2,有返回    3,异步任务

 

 

 Future(FutureTask) 优缺点

优点:future+线程池异步多线程任务配合,能显著提高程序的运行效率

缺点: 调用get()方法求结果,一旦计算没有完成,会导致程序阻塞  

   如果采用轮询的机制,判断是否完成 while(futureTask.isDone()) , 完成后调用get()方法返回结果,缺点是比较耗费性能,

所以,future对于结果的获取不是很友好,只能通过阻塞或者轮询的方式去获取结果。

completableFuture

java8在Future的基础上新增了completableFuture,有如下新特性

1,可以传入回调对象,当任务完成或异常时,自动调用回调对象的回调方法(规避了future的缺点)

2,多个任务前后依赖组合处理

3,对计算速度选最快

 

创建completableFure有四个静态方法 (也可以通过new创建,但不推荐)

runAsync无返回值

  public static CompletableFuture<Void> runAsync(Runnable runnable)

  public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)

supplyAsync无返回值

  public static <U>CompletableFuture<U> supplyAsync(Supplier<U> supplier)

  public static <U>CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)

 

CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{
            System.out.println(Thread.currentThread().getName());
        }, //此处可以指定线程池   );
        System.out.println(completableFuture.get());

返回结果

 

 

 

        ExecutorService threadPool = Executors.newFixedThreadPool(3);
        CompletableFuture<String> completableFuture2 = CompletableFuture.supplyAsync(()->{
            System.out.println(Thread.currentThread().getName());
            return "this is supplyAsync";
        },threadPool);
        System.out.println(completableFuture2.get());

返回结果

 

 

 通过.whenComplete和.exceptionally实现任务完成或抛出异常时执行的步骤

       /*
    注意:最好使用自己创建的线程池,如果用默认的ForkJoinPool的话,ForkJoinPool会随着主线程执行完一起销毁,
    可能会导致completableFuture执行不玩完,没有返回结果
    */
    ExecutorService threadPool = Executors.newFixedThreadPool(3); CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(()->{ System.out.println(Thread.currentThread().getName() + "come in"); int result = ThreadLocalRandom.current().nextInt(10); try {TimeUnit.MILLISECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();} System.out.println("1秒钟后出结果:" + result);
       //模拟异常 int i = result / 0; return result; },threadPool).whenComplete((v,e)-> { if ( e == null){ System.out.println("----计算完成,更新系统value = " + v); } }).exceptionally(e -> { e.printStackTrace(); System.out.println("异常情况" + e.getCause() + "\t" + e.getMessage()); return null; }); System.out.println(Thread.currentThread().getName() + "主线程先去忙其他任务"); threadPool.shutdown(); }

返回结果(正常情况)

 

(异常情况)

 

 

 

 CompletableFuture关于线程池选择

1没有传入自定义线程池,都用默认线程池ForkJoinPool;
2传入了一一个自定义线程池,
如果你执行第一一个任务的时候,传入了一个自定义线程池:
调用thenRun方法执行第:二个任务时,则第二个任务和第-一个任务是共用同一个线程池。
调用thenRunAsync执行第二个任务时
则第一个任务使用的是你自己传入的线程池,第二个任务使用的是ForkJoin线程池
3备注
有可能处理太快,系统优化切换原则,直接使用main线程处理
其它如: thenAccept和thenAcceptAsync, thenApply 和thenApplyAsync等,它们之间的区别也是同理

线程中断的三个方法

 

 

 

*线程中断的思想: 一个线程应该自己决定自己的命运,不该由其他线程来强行中断或停止,所以中断是一种协商机制

 

三种线程唤醒对比

方法1: synchronized, wait(), notify()

object objectLock = new object();
new Thread(() -> {
synchronized (objectLock){
System. out . println( Thread. current Thread(). getName()+"\t ----come in");
try {
objectLock .wait();
} catch (InterruptedException e) {
e. printStackTrace();
System. out . println(Thread . current Thread(). getName()+"\t ---- 被唤醒");
}
}, name: "t1"). start();
//暂停几秒钟线程
try { TimeUnit .SECONDS . sleep( timeout: 1); } catch (InterruptedException e) { e. printstackTrace(); }
new Thread(() ->{
synchronized (objectLock){
objectlock.notify();
System. out . println( Thread. current Thread().getName()+"\t |");
}
}, name: "t2").start();

 

方法2: Lock, condition.wait(), condition.signal()

new Thread(() -> {
lock.1ock();
try {
System. out . println( Thread. current Thread(). getName()+"\t ----come in");
condition. await(); 
System. out . println(Thread . current Thread(). getName()+"\t ---- 被唤醒");
} catch (InterruptedException e) {
e. printStackTrace();
} finally {
lock.unlock();
}
}, name: "t1"). start();
//暂停几秒钟线程
try { TimeUnit . SECONDS . sleep( timeout: 1); } catch (InterruptedException e) { e. printStackTrace(); }
new Thread(() -> {
lock.1ock();
try
condition. signal();
System. out . println( Thread. current Thread(). getName()+"\t ----发出通知");
S中。
}finally {
lock . unlock();
}

 

方法3: LockSupport, static park(), static unpark()

public static void main(String[] args)
Thread t1 = new Thread(() -> {
try { TimeUnit .SECONDS.sleep( timeout:3); } catch (InterruptedException e) { e.printstackTrace(); }
System. out . println(Thread. current Thread( ).getName() + "\t ----come in"+System. currentT imeMillis());
LockSupport . park();
System . out . println(Thread . current Thread() . getName() + "\t ---- 被唤醒" +System. currentTimeMillis());
},name: "t1");
t1.start();
//暂停几秒钟线程
//try { TimeUnit. SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
new Thread(() -> {
LockSupport . unpark(t1);
System. out . println( Thread . current Thread() . getName()+"\t ----发出通知");
}, name: "t2").start();
}

 

对比:synchronized和lock的唤醒需要在锁块内进行,并且需要先等待,后唤醒。

   LockSupport没有锁的要求,并且可以先给线程一个通行证,让线程在收到下一个等待指令时跳过等待。无论执行多少次unpark(),通行证只能储存一个,如果线程收到连续两个park()指令,第二条park指令仍然会让线程等待。

标签:Thread,getName,System,线程,println,CompletableFuture,out
From: https://www.cnblogs.com/tyleaf/p/16981053.html

相关文章

  • JDK源码之CompletableFuture(三)anyOf,allOf是怎么实现的?
    ​​JDK源码之CompletableFuture(一)结果返回原理​​JDK源码之CompletableFuture(二)链式调用原理JDK源码之CompletableFuture(三)anyOf,allOf是怎么实现的?目录​​一、全部返回......
  • JDK源码之CompletableFuture(二)链式调用原理
    ​​JDK源码之CompletableFuture(一)结果返回原理​​JDK源码之CompletableFuture(二)链式调用原理JDK源码之CompletableFuture(三)anyOf,allOf是怎么实现的?目录​​一、第一步调......
  • 开流运行多线程CompletableFuture
    CompletableFuture提高接口性能//根据排口查询因子信息(异步)CompletableFuture<List<FactorInfo>>listCompletableFuture=CompletableFuture.supplyAsyn......
  • Java并发编程——CompletableFuture详解
    一、简介JDK5引入了Future模式。Future接口是Java多线程Future模式的实现,在java.util.concurrent包中,可以来进行异步计算。Future模式是多线程设计常用的一种设计模式。Fut......
  • java8 CompletableFuture异步调用与lamda结合
    前言:jdk1.8 lamda记录异步执行动作staticvoidthenApplyAsyncExample(){CompletableFuture<String>cf=CompletableFuture.completedFuture("message").thenApplyAs......
  • CompletableFuture&CompletionStage用法
    CompletableFuture&CompletionStage用法知识点:同步和异步线程池,三大方法CompletableFuturecompletedFuturerunAsyncthenApply所有执行程序见文末1,背景概述......
  • CompletableFuture源码解析
    前言JDK8为我们带来了CompletableFuture这个有意思的新类,它提供比Future更灵活更强大的回调功能,借助CompletableFuture我们可以更方便的编排异步任务。本着知其然......
  • CompletableFuture 常用方法小抄
    关于CompletableFuture,引用baeldung中的一句话:ThebestpartoftheCompletableFutureAPIistheabilitytocombineCompletableFutureinstancesinachainof......
  • CompletableFuture异步任务编排
    业务场景:查询详情页的逻辑比较多,有些数据还需要远程调用,必然要花费更多的时间。1、获取SKU的基本信息0.5s2、获取SKU的图片信息0.5s3、获取SKU的促销信息1s4、获取SPU的......
  • CompletableFuture异步编程
    1、创建/***publicstatic<U>CompletableFuture<U>supplyAsync(Supplier<U>supplier){..}*publicstatic<U>CompletableFuture<U>supplyAsync(Suppl......