先学习一下什么是异步编程:异步编程
FutureTask可用于异步获取执行结果或取消执行任务的场景。经过传入Runnable或者Callable的任务给FutureTask,直接调用其run方法或者放入线程池执行,以后能够在外部经过FutureTask的get方法异步获取执行结果,所以,FutureTask很是适合用于耗时的计算,主线程能够在完成本身的任务后,再去获取结果。另外,FutureTask还能够确保即便调用了屡次run方法,它都只会执行一次Runnable或者Callable任务,或者经过cancel取消FutureTask的执行等。
CompletableFuture的使用
线程池的创建:
ExecutorService threadPool = Executors.newFixedThreadPool(2);
FutureTask的get方法必须之行结束以后才能执行主线程,容易阻塞,所以需要CompletableFuture。
1.1CompletableFuture的创建
注意:不建议使用new的方法创建CompletableFuture,推荐以下四种方法。
//runAsync方法不支持返回值
1. public static CompletableFuture<Void> runAsync(Runnable runnable)
2. public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
//supplyAsync可以支持返回值
3. public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
4. public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
- 没有指定Executor的方法会使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码。如果指定线程池,则使用指定的线程池运行。以下所有的方法都类同
- 因为CompletableFuture是异步任务,所以一般费时间的计算量大的放到这里面来
public class CompletableFutureTest { public static void main(String[] args) throws Exception{ ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 5, 2L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(3)); //(1). CompletableFuture.runAsync(Runnable runnable); CompletableFuture future1=CompletableFuture.runAsync(()->{ System.out.println(Thread.currentThread().getName()+"*********future1 coming in"); }); //这里获取到的值是null System.out.println(future1.get()); //(2). CompletableFuture.runAsync(Runnable runnable,Executor executor); CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> { //ForkJoinPool.commonPool-worker-9 System.out.println(Thread.currentThread().getName() + "\t" + "*********future2 coming in"); }, executor); //(3).public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) CompletableFuture<Integer> future3 = CompletableFuture.supplyAsync(() -> { //pool-1-thread-1 System.out.println(Thread.currentThread().getName() + "\t" + "future3带有返回值"); return 1024; }); System.out.println(future3.get()); //(4).public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor) CompletableFuture<Integer> future4 = CompletableFuture.supplyAsync(() -> { System.out.println(Thread.currentThread().getName() + "\t" + "future4带有返回值"); return 1025; }, executor); System.out.println(future4.get()); //关闭线程池 executor.shutdown(); } }
1.2CompletableFuture的API
-
1.获取结果
-
2.对计算结果进行处理(thenApply、handle)
3.对计算结果进行消费
4.对计算速度进行选用(applyToEither、acceptEither、runAfterEither)
applyToEither:两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值
acceptEither:两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值
runAfterEither:两个任务有一个执行完成,不需要获取 future 的结果,处理任务,也没有返回值
5.对计算结果进行合并(thenCombine、thenAcceptBoth、runAfterBoth)