一、CompletableFuture 常用方法
3、对计算结果进行消费
1、对比补充
- thenRun(Runable runable)
- 任务A执行完任务B,并且B不需要A的结果
- thenAccept(Consumer action)
- 任务A执行完执行任务B,B需要A的结果,但是任务B无返回值
- thenApply(Function fn)
- 任务A执行完执行任务B,B需要A的结果,同时任务B有返回值
2、CompletableFuture和线程池说明
- 任务A执行完执行任务B,B需要A的结果,同时任务B有返回值
- 没有传入自定义线程池,都是用默认线程池ForkJoinPool
- 传入 一个自定义线程池
- 如果你执行第一个任务的时候 ,传入了一个自定义线程池
- 调用thenRun方法执行第二个任务时,则第二个任务和第一个任务共用一个线程池
- 调用thenRunAsync执行第二个任务时,则第一个任务使用的是你自己传入的线程池,第二个任务使用的是ForkJoinPool线程池
- 备注
- 有可能处理太快,系统优化切换原则,直接使用main线程处理
//线程池说明
public class CompletableFutureWithThreadPool {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(5);
try {
CompletableFuture future = CompletableFuture.supplyAsync(() -> {
// try {
// Thread.sleep(20);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
System.out.println(“一号任务” + Thread.currentThread().getName());
return “abcd”;
},threadPool).thenRun(() -> {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“二号任务” + Thread.currentThread().getName());
}).thenRun(() -> {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“三号任务” + Thread.currentThread().getName());
}).thenRun(() -> {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“四号任务” + Thread.currentThread().getName());
}).thenRun(() -> {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“五号任务” + Thread.currentThread().getName());
});
future.get(2, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
}
源码分析为什么会有区别
public CompletableFuture thenRun(Runnable action) {
return uniRunStage(null, action);
}
public CompletableFuture thenRunAsync(Runnable action) {
return uniRunStage(asyncPool, action);
}
private static final boolean useCommonPool =
(ForkJoinPool.getCommonPoolParallelism() > 1);
/**- Default executor – ForkJoinPool.commonPool() unless it cannot
- support parallelism.
很明显这里创建了新的线程池返回出去了 ThreadPerTaskExecutor
*/
private static final Executor asyncPool = useCommonPool ?
ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
4、对计算速度进行选用
CompletableFuture applyToEither( CompletionStage<? extends T> other, Function<? super T, U> fn)
选取两个线程中最快的线程,作为应用
public class CompletableFutureFastDemo {
public static void main(String[] args) {
CompletableFuture futureA = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
return “resultA”;
});
CompletableFuture futureB = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return “resultB”;
});
//applyToEither选取一个速度最快的作为应用
CompletableFuture future = futureA.applyToEither(futureB, f -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return “applyC” + f;
});
System.out.println(Thread.currentThread().getName() + “------result:” + future.join());
}
}
5、对计算结果合并
thenCombine()两个任务CompletionStage任务都完成后,最终指向两个任务的结果一起交给thenCombine来处理
public class CompletableFutureCombineDemo {
public static void main(String[] args) {
CompletableFuture future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“任务一执行”);
return 10;
});
CompletableFuture future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“任务二执行”);
return 20;
});
CompletableFuture future = future1.thenCombine(future2, (x, y) -> {
System.out.println(“开始合并”);
return x + y;
});
System.out.println(future.join());
}
}
- 有可能处理太快,系统优化切换原则,直接使用main线程处理