JUC-CompletableFuture

FutureTask 

JUC-CompletableFuture_第1张图片

    public static void main(String[] args) throws Exception {
        FutureTask futureTask = new FutureTask<>(() -> {
            System.out.println(Thread.currentThread().getName() + " come in");
            try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }
            return 1024;
        });
        new Thread(futureTask).start();
       /* System.out.println(futureTask.get()); // get()会阻塞直到线程完成才会继续执行
        System.out.println(futureTask.get(2L, TimeUnit.SECONDS)); // 带过期时间的阻塞*/
        //不要阻塞,尽量用轮询替代
        while(true){
            if(futureTask.isDone()){
                System.out.println("----result: "+futureTask.get());
                break;
            }else{
                System.out.println("还在计算中,别催,越催越慢,再催熄火");
            }
        }
    }

get()和join()都能获取返回结果,也都会阻塞

get()阻塞,一旦调用get(),不管计算是否完成都会导致阻塞

isDone()轮询,如果想要异步获取结果,通常都会以轮询的方式去获取结果,尽量不要阻塞。轮询的方式会额外消耗的CPU资源。

如何避免阻塞了?引入了CompletableFuture

JUC-CompletableFuture_第2张图片

 CompletionStage:代表异步计算过程中的某一个阶段,一个阶段完成以后可能会触发另一个阶段

  • 一个阶段的计算执行可以是Function,Consumer或者Runnable
  • 一个阶段的执行可能是被单个阶段的完成触发,也可能是由多个阶段一起触发

CompletableFuture:在Java8中CompletableFuture提供了非常强大的future的扩展功能,可以帮助我们简化异步编程的复杂性,并且提供了函数式编程的能力,可以通过回调的方式处理计算结果,也提供了转换和组合CompletableFuture的方法。

  • 它可能代表一个明确完成的future,也可能代表一个完成阶段(CompletionStage)。它支持在计算完成以后触发一些函数或执行某些动作。
  • 它实现了future和CompletionStage的接口。

它有四个核心的静态方法来创建一个异步操作

无返回值

public static CompletableFuture runAsync(Runnable runnable);

public static CompletableFuture runAsync(Runnable runnable, Executor executor);

有返回值

public static  CompletableFuture supplyAsync(Supplier supplier);

public static  CompletableFuture supplyAsync(Supplier supplier, Executor executor)

JUC-CompletableFuture_第3张图片

  • 不指定Executor,使用默认的ForkJoinPool.commonPool()作为它的线程池执行异步代码,它的缺点是用户线程结束后默认的线程池会销毁,则异步线程的代码就不会执行
  • 强烈建议 CompletableFuture配合Excutor使用
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 20, 1, TimeUnit.MINUTES,
                new LinkedBlockingQueue<>(50), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());
        CompletableFuture exceptionally = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + " come in");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 2;
        }, executor).whenComplete((v, e) -> {
            if (e == null) {
                System.out.println("result = " + v);
            }
        }).exceptionally(e -> {
            e.printStackTrace();
            return null;
        });
        // get()和join()都能获取返回结果,也都会阻塞
        // exceptionally.get(); // 会抛出异常ExecutionException, InterruptedException
        // exceptionally.join(); // 和不会抛出异常,推荐使用join()获取结果
        // CompletableFuture要使用自定义创建的线程池,如果使用默认的线程池,则主线程结束后默认的线程池就会销毁,异步线程的代码就不会执行
        executor.shutdown();
        System.out.println("main thread over");
    }

JUC-CompletableFuture_第4张图片

  •  get()和join()都能获取返回结果,也都会阻塞
  • get()会抛出异常ExecutionException, InterruptedException,join()不会抛出异常,推荐使用join()获取结果

 进微信群和大佬面对面学习交流

JUC-CompletableFuture_第5张图片

 

你可能感兴趣的:(面试,多线程,java)