开始阶段通过Callable和FutureTask获取结果,为了异步执行之后获取线程结果。 主线程不中断继续执行,开启子线程异步去执行其他操作。
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
FutureTask task1 = new FutureTask(()->{
try{ TimeUnit.MILLISECONDS.sleep(5000);}catch(InterruptedException e) {e.printStackTrace();}
return "task1 over";
});
Thread t1 = new Thread(task1,"t1");
t1.start();
// System.out.println(task1.get()); //调用get(),就会阻塞,不见不散,非要等到结果才会离开
System.out.println(task1.get(3,TimeUnit.SECONDS));
System.out.println(Thread.currentThread().getName()+"----忙其他任务了");
}
isDone() [判断是否完成]轮询 容易引起cpu空转,耗费更多的资源
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
FutureTask task1 = new FutureTask(()->{
try{ TimeUnit.MILLISECONDS.sleep(5000);}catch(InterruptedException e) {e.printStackTrace();}
return "task1 over";
});
Thread t1 = new Thread(task1,"t1");
t1.start();
// System.out.println(task1.get()); //调用get(),就会阻塞,不见不散,非要等到结果才会离开
// System.out.println(task1.get(3,TimeUnit.SECONDS));
System.out.println(Thread.currentThread().getName()+"----忙其他任务了");
// System.out.println(task1.get());
while (true){
if(task1.isDone()){
System.out.println(task1.get());
break;
}else{
try{ TimeUnit.MILLISECONDS.sleep(300);}catch(InterruptedException e) {e.printStackTrace();}
System.out.println("正在处理中.......");
}
}
}
CompletableFuture 提供了四个静态方法来创建一个异步操作。
public static CompletableFuture runAsync(Runnable runnable);
public static CompletableFuture runAsync(Runnable runnable, Executor executor);
public static CompletableFuture supplyAsync(Supplier supplier);
public static CompletableFuture supplyAsync(Supplier supplier, Executor executor);
说明:没有指定Executor的方法会使用 ForkJoinPool.commonPool() 作为它的线程池执行异步代码。如果指定线程池,则使用指定的线程池运行。
①、runXxxx都是没有返回结果的,supplyXxx都是可以获取返回结果的
②、可以传入自定义的线程池,否则就用默认的线程池。
当CompletableFuture的计算结果完成,或者抛出异常的时候,可以执行特定的Action。主要是下面的方法:
注意下面CompletableFuture的回调方法参数是BiConsumer,包含两个参数,当返回值是null或者没有异常的情况下,都会接收。允许null!
public interface BiConsumer {
void accept(T var1, U var2);
default BiConsumer andThen(BiConsumer super T, ? super U> after) {
Objects.requireNonNull(after);
return (l, r) -> {
this.accept(l, r);
after.accept(l, r);
};
}
}
方法体权限 public 和 返回值 CompletableFuture
whenComplete(BiConsumer super T,? super Throwable> action);
方法完成后的感知处理
返回相同的结果或例外,这一阶段的新completionstage,
这个阶段完成时,执行特定动作的结果和异常,这个阶段。
whenCompleteAsync(BiConsumer super T,? super Throwable> action);
返回相同的结果或例外,这一阶段的新completionstage,
这个阶段完成时,执行特定动作执行给定的操作这一阶段的默认的异步执行设施,
其结果和异常,这个阶段作为参数。
whenCompleteAsync(BiConsumer super T,? super Throwable> action,
Executor executor);
返回相同的结果或例外,这一阶段的新completionstage,
这个阶段完成时,执行使用所提供的遗嘱执行人,
给出的行动与结果和异常,这个阶段作为参数。
public CompletableFuture exceptionally(Function fn);
方法出现异常后的处理,出现异常返回默认值
返回一个新的completablefuture已经完成与给定值。
handle((t,u)
跟whenComplete基本一致,区别在于handle的回调方法有返回值,能够重新设置返回值
public CompletableFuture thenApply(Function super T,? extends U> fn)
public CompletableFuture thenApplyAsync(Function super T,? extends U> fn)
public CompletableFuture thenApplyAsync(Function super T,? extends U> fn, Executor executor)
当一个线程依赖另一个线程时,获取上一个任务返回的结果,**并返回当前任务的返回值**。(有返回值)
public CompletionStage thenAccept(Consumer super T> action);
public CompletionStage thenAcceptAsync(Consumer super T> action);
public CompletionStage thenAcceptAsync(Consumer super T> action,Executor executor);
消费处理结果。接收任务的处理结果,并消费处理,**无返回结果。
public CompletionStage thenRun(Runnable action);
public CompletionStage thenRunAsync(Runnable action);
public CompletionStage thenRunAsync(Runnable action,Executor executor);
只要上面的任务执行完成,就开始执行thenRun,**只是处理完任务后,执行 thenRun的后续操作
每一个方法都对应了三种操作。带有Async默认是异步执行的。这里所谓的异步指的是不在当前线程内执行。带有参数Executor executor的则用指定的线程池方案,不指定的话则用默认的ForkJoinPool.commonPool()。
说明:(Function fn)
T : 上一个任务返回结果的类型
U:当前任务的返回值的类型
两个任务必须都完成,触发该任务。
thenCombine:组合两个future,获取两个future任务的返回结果,并返回当前任务的返回值
thenAcceptBoth:可以感知前两个结果,组合两个future,获取两个future任务的返回结果,然后处理任务,没有返回值。
runAfterBoth:无法感知前两个结果,组合两个future,不需要获取future的结果,只需两个future处理完任务后,处理该任务
当两个任务中,任意一个future任务完成的时候,执行任务。
applyTOEither:两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值。
acceptEither:两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值。
runAfterEither:两个任务有一个执行完成,不需要获取 future的结果,处理任务,也没有返回值。
public static CompletableFuture allOf(CompletableFuture>... cfs);
public static CompletableFuture
说明:
allOf:等待所有任务完成
anyOf:只要有一个任务完成
// 如果完成则返回结果,否则就抛出具体的异常
public T get() throws InterruptedException, ExecutionException
// 最大时间等待返回结果,否则就抛出具体异常
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
// 完成时返回结果值,否则抛出unchecked异常。为了更好地符合通用函数形式的使用,如果完成此 CompletableFuture所涉及的计算引发异常,则此方法将引发unchecked异常并将底层异常作为其原因
public T join()
// 如果完成则返回结果值(或抛出任何遇到的异常),否则返回给定的 valueIfAbsent。
public T getNow(T valueIfAbsent)
// 如果任务没有完成,返回的值设置为给定值
public boolean complete(T value)
// 如果任务没有完成,就抛出给定异常
public boolean completeExceptionally(Throwable ex)
没有传入自定义线程池,都用默认线程池ForkJoinPool。
传入了一个自定义线程池,执行第一个任务的时候,传入了一个自定义线程池;thenRun方法执行第二次,则第二个任务和第一个任务共用一个线程池。thenRunAsync执行第二个任务,第一个任务是使用的自己传入的线程池,第二个任务使用的是ForkJoinPool线程池。
如果处理速度太快,系统优化切换原则,直接使用main线程;
其他如:thenAccept和thenAcceptAsync,thenApply和thenApplyAsync等;它们之间是同理。