zoukankan      html  css  js  c++  java
  • CompletableFuture引入

    一、Future介绍    

    Future
    以前我们如果有个方法action执行,比如去数据库中查询数据、上传一个文件等,这个方法执行10分钟,调用者就需要等10分钟。
    基于此,调用者可以先执行action,返回一个票据future,然后可以继续做其他的事情,这样就不阻塞了,完全异步化。然后可以根据future拿到action的结果。

    自己怎么实现一个Future呢?

    代码例子:

     1 package com.cy.java8;
     2 
     3 import java.util.concurrent.atomic.AtomicBoolean;
     4 import java.util.concurrent.atomic.AtomicReference;
     5 
     6 public class FutureInAction {
     7     public static void main(String[] args) throws InterruptedException {
     8         Future<String> future = invoke(() -> {
     9             try {
    10                 Thread.sleep(10000);
    11                 return "I am finished";
    12             } catch (InterruptedException e) {
    13                 return "error";
    14             }
    15         });
    16 
    17         System.out.println(future.get());
    18         System.out.println(future.get());
    19         System.out.println(future.get());
    20         //do other thing...
    21 
    22         while (!future.isDone()) {
    23             Thread.sleep(10);
    24         }
    25         System.out.println(future.get());
    26     }
    27 
    28     /**
    29      * 以前阻塞式的方式
    30      *
    31      * @param callable
    32      * @param <T>
    33      * @return
    34      */
    35     private static <T> T block(Callable<T> callable) {
    36         return callable.action();
    37     }
    38 
    39     /**
    40      * Future异步方式
    41      *
    42      * @param callable
    43      * @param <T>
    44      * @return
    45      */
    46     private static <T> Future<T> invoke(Callable<T> callable) {
    47         AtomicReference<T> result = new AtomicReference<>();
    48         AtomicBoolean finished = new AtomicBoolean(false);
    49         Thread t = new Thread(() -> {
    50             T value = callable.action();
    51             result.set(value);
    52             finished.set(true);
    53         });
    54         t.start();
    55 
    56         Future<T> future = new Future<T>() {
    57             @Override
    58             public T get() {
    59                 return result.get();
    60             }
    61 
    62             @Override
    63             public boolean isDone() {
    64                 return finished.get();
    65             }
    66         };
    67         return future;
    68     }
    69 
    70     private interface Future<T> {
    71         T get();
    72 
    73         boolean isDone();
    74     }
    75 
    76     private interface Callable<T> {
    77         T action();
    78     }
    79 }

    console打印:

    null
    null
    null
    I am finished
    

    二、jdk自带的Future介绍

     1 package com.cy.java8;
     2 
     3 import java.util.concurrent.*;
     4 
     5 public class FutureInAction2 {
     6     public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
     7         /**
     8          * 创建了一个线程池,但这个线程池里面只有1根线程,单线程
     9          * 这个线程是可以复用的,它执行完之后不会消失,会始终保持等待另外一个任务去执行
    10          * 所以main函数执行结束之后,它不会退出的,所以还要shutdown
    11          */
    12         ExecutorService executorService = Executors.newSingleThreadExecutor();
    13         Future<String> future = executorService.submit(() -> {
    14             try {
    15                 Thread.sleep(10000);
    16                 return "I am finished.";
    17             } catch (InterruptedException e) {
    18                 return "I am error.";
    19             }
    20         });
    21 
    22         //do other thing...
    23 
    24         /**
    25          * jdk的future和我们自己写的不一样,它get的时候会阻塞住,如果没有结果它就阻塞住了,一直等结果
    26          */
    27         //String value = future.get();
    28         //System.out.println(value);
    29 
    30         //最多等10秒,如果没有拿到结果就拉倒,抛TimeoutException
    31         //String value2 = future.get(10000, TimeUnit.MILLISECONDS);
    32         //System.out.println(value2);
    33 
    34         while(!future.isDone()){
    35             Thread.sleep(10);
    36         }
    37         System.out.println(future.get());
    38 
    39         executorService.shutdown();
    40     }
    41 }

    三、CompletableFuture引入

    能不能future的任务执行完成之后,你来回调我呢?异步回调,你完成了之后来回调我。
    就像ajax的异步回调,post请求完成之后回调函数,来执行其他的东西。
    CompletableFuture最大的作用就是干这个的。

    在讲CompletableFuture之前,先说下它的原理,自己模拟实现一个CompletableFuture.

    模拟代码例子:

     1 package com.cy.java8;
     2 
     3 import java.util.concurrent.atomic.AtomicBoolean;
     4 import java.util.concurrent.atomic.AtomicReference;
     5 
     6 public class FutureInAction3 {
     7     public static void main(String[] args) {
     8         invoke(() -> {
     9             try {
    10                 Thread.sleep(3000);
    11                 return "I am finished.";
    12             } catch (InterruptedException e) {
    13                 return "I am error.";
    14             }
    15         }).setCompletable(new Completable<String>() {
    16             @Override
    17             public void complete(String s) {
    18                 System.out.println("complete. value = " + s);
    19             }
    20 
    21             @Override
    22             public void exception(Throwable e) {
    23                 System.out.println("error...");
    24                 e.printStackTrace();
    25             }
    26         });
    27 
    28         //do other thing...
    29         System.out.println("do other thing...");
    30     }
    31 
    32     private static <T> Future<T> invoke(Callable<T> callable) {
    33         AtomicReference<T> result = new AtomicReference<>();
    34         AtomicBoolean finished = new AtomicBoolean(false);
    35 
    36         Future<T> future = new Future<T>() {
    37             private Completable<T> completable;
    38 
    39             @Override
    40             public T get() {
    41                 return result.get();
    42             }
    43 
    44             @Override
    45             public boolean isDone() {
    46                 return finished.get();
    47             }
    48 
    49             @Override
    50             public void setCompletable(Completable<T> completable) {
    51                 this.completable = completable;
    52             }
    53 
    54             @Override
    55             public Completable<T> getCompletable() {
    56                 return completable;
    57             }
    58         };
    59 
    60         Thread t = new Thread(() -> {
    61             try {
    62                 T value = callable.action();
    63                 result.set(value);
    64                 finished.set(true);
    65                 if (future.getCompletable() != null) {
    66                     future.getCompletable().complete(value);
    67                 }
    68             } catch (Throwable cause) {
    69                 if (future.getCompletable() != null) {
    70                     future.getCompletable().exception(cause);
    71                 }
    72             }
    73         });
    74         t.start();
    75 
    76         return future;
    77     }
    78 
    79     private interface Future<T> {
    80         T get();
    81 
    82         boolean isDone();
    83 
    84         void setCompletable(Completable<T> completable);
    85 
    86         Completable<T> getCompletable();
    87     }
    88 
    89     private interface Completable<T> {
    90         void complete(T t);
    91 
    92         void exception(Throwable cause);
    93     }
    94 
    95     private interface Callable<T> {
    96         T action();
    97     }
    98 }

    console打印:

    do other thing...
    complete. value = I am finished.  

    ----

  • 相关阅读:
    百度地图学习
    JS中call和apply区别有哪些 记录
    初次学习AngularJS
    C#中Abstract和Virtua笔记,知识
    css学习笔记四
    css学习笔记三
    jquery基础 笔记三
    jquery基础 笔记二
    jquery基础 笔记一
    负边距在布局中的应用
  • 原文地址:https://www.cnblogs.com/tenWood/p/11610284.html
Copyright © 2011-2022 走看看