get()和join()都能获取返回结果,也都会阻塞FutureTask?
public static void main(String[] args) throws Exception {
FutureTask<Integer> 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()阻塞,一旦调用get(),不管计算是否完成都会导致阻塞
isDone()轮询,轮询的方式会小号额外的CPU资源,如果想要异步获取结果,通常都会以轮询的方式去获取结果,尽量不要阻塞
如何避免阻塞了?引入了CompletableFuture
?CompletionStage:代表异步计算过程中的某一个阶段,一个阶段完成以后可能会触发另一个阶段
- 一个阶段的计算执行可以是Function,Consumer或者Runnable
- 一个阶段的执行可能是被单个阶段的完成触发,也可能是由多个阶段一起触发
CompletableFuture:在Java8中CompletableFuture提供了非常强大的future的扩展功能,可以帮助我们简化异步编程的复杂性,并且提供了函数式编程的能力,可以通过回调的方式处理计算结果,也提供了转换和组合CompletableFuture的方法。
- 它可能代表一个明确完成的future,也可能代表一个完成阶段(CompletionStage)。它支持在计算完成以后触发一些函数或执行某些动作。
- 它实现了future和CompletionStage的接口。
它有四个核心的静态方法来创建一个异步操作
无返回值
public static CompletableFuture<Void> runAsync(Runnable runnable);
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor);
有返回值
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
- 不指定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<Integer> 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");
}
- ?get()和join()都能获取返回结果,也都会阻塞
- get()会抛出异常ExecutionException, InterruptedException,join()不会抛出异常,推荐使用join()获取结果
|