public FuturegetPriceAsync(String product) { //创建 CompletableFuture 对象,对象中包含异步计算结果 CompletableFuture futurePrice = new CompletableFuture<>(); //新建线程计算商品价格 new Thread(() -> { try { double price = calculatePrice(product); //将异步计算得到的结果设置到 CompletableFuture 中, futurePrice.complete(price); } catch (Exception e) { futurePrice.completeExceptionally(e); } }).start(); //无需等待计算结果,直接返回 CompletableFuture 对象 return futurePrice; }
runAsync 创建没有返回值的异步任务。它有如下两个方法,一个是使用默认线程池(ForkJoinPool.commonPool())的方法,一个是自定义线程池的重载方法
package cn.netkiller; import cn.netkiller.thread.ThreadManager; import lombok.SneakyThrows; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Main { @SneakyThrows public static void main(String[] args) { CompletableFuture.runAsync(() -> { System.out.println("do something..."); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } }); ExecutorService executorService = Executors.newSingleThreadExecutor(); CompletableFuture.runAsync(() -> { System.out.println("do something..."); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } }, executorService); CompletableFuturecompletableFuture = CompletableFuture.runAsync(() -> { System.out.println("do something...."); // Thread.currentThread().setName("测试有返回值的异步执行"); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } }); ThreadManager tm = new ThreadManager(); System.out.println(tm.show()); try { Thread.sleep(5000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("Result ->" + completableFuture.isDone()); } }
do something... do something... do something.... ======================================================================================= | ID | Name | Group | Daemon | State | Priority | --------------------------------------------------------------------------------------- | 1 | main | main | false | RUNNABLE | 5 | | 21 | ForkJoinPool.commonPool-worker-1 | main | true | TIMED_WAITING | 5 | | 22 | pool-1-thread-1 | main | false | TIMED_WAITING | 5 | | 23 | ForkJoinPool.commonPool-worker-2 | main | true | TIMED_WAITING | 5 | ======================================================================================= Result ->true
package cn.netkiller.test; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicInteger; public class Test { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println(Thread.currentThread()); AtomicInteger variable = new AtomicInteger(0); CompletableFuturerunAsync = CompletableFuture.runAsync(() -> process(variable)); runAsync.join(); System.out.println(variable.get()); } public static void process(AtomicInteger variable) { System.out.println(Thread.currentThread().getName() + " Process..."); variable.set(1024); } }
thenRun/thenRunAsync 功能是什么?完成前置任务之后,自己在执行。
thenRun/thenRunAsync 区别是什么?thenRun 使用同一个线程执行任务,thenRunAsync 会再开一个新线程执行任务。
@GetMapping("/completableFutureRun") public String completableFutureRun() { CompletableFuturecompletableFuture = CompletableFuture.runAsync(() -> { System.out.println(Thread.currentThread().getName() + " - CompletableFuture 前置任务"); try { Thread.sleep(5 * 1000); } catch (InterruptedException e) { throw new RuntimeException(e); } }); CompletableFuture thenRun = completableFuture.thenRun(() -> { System.out.println(Thread.currentThread().getName() + " - 接着执行第二个 thenRun 任务"); }); CompletableFuture thenRunAsync = completableFuture.thenRunAsync(() -> { System.out.println(Thread.currentThread().getName() + " - 接着执行第二个 thenRunAsync 任务"); }); return "Done"; }
运行结果
ForkJoinPool.commonPool-worker-1 - CompletableFuture 前置任务 ForkJoinPool.commonPool-worker-1 - 接着执行第二个 thenRun 任务 ForkJoinPool.commonPool-worker-2 - 接着执行第二个 thenRunAsync 任务
这里可以看到 thenRunAsync 的线程变化,开启新线程 ForkJoinPool.commonPool-worker-2 处理任务
supplyAsync 创建带有返回值的异步任务。它有如下两个方法,一个是使用默认线程池(ForkJoinPool.commonPool())的方法,一个是带有自定义线程池的重载方法
// 带返回值异步请求,默认线程池 public static CompletableFuture supplyAsync(Supplier supplier) // 带返回值的异步请求,可以自定义线程池 public static CompletableFuture supplyAsync(Supplier supplier, Executor executor)
package cn.netkiller; import cn.netkiller.thread.ThreadManager; import lombok.SneakyThrows; import java.util.concurrent.CompletableFuture; public class Main { @SneakyThrows public static void main(String[] args) { CompletableFuturecompletableFuture = CompletableFuture.supplyAsync(() -> { System.out.println("do something...."); return "done"; }); System.out.println("Result ->" + completableFuture.get()); ThreadManager tm = new ThreadManager(); System.out.println(tm.show()); } }
运行结果
do something.... Result ->done ======================================================================================= | ID | Name | Group | Daemon | State | Priority | --------------------------------------------------------------------------------------- | 1 | main | main | false | RUNNABLE | 5 | | 21 | ForkJoinPool.commonPool-worker-1 | main | true | TIMED_WAITING | 5 | =======================================================================================
package cn.netkiller; import cn.netkiller.thread.ThreadManager; import lombok.SneakyThrows; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Main { @SneakyThrows public static void main(String[] args) { ExecutorService executorService = Executors.newSingleThreadExecutor(); CompletableFuturecompletableFuture = CompletableFuture.supplyAsync(() -> { System.out.println("do something...."); try { Thread.sleep(30000); } catch (InterruptedException e) { throw new RuntimeException(e); } return "done"; }, executorService); System.out.println("Result ->" + completableFuture.get()); ThreadManager tm = new ThreadManager(); System.out.println(tm.show()); } }