查询详情页的逻辑比较多,有些数据还需要远程调用,必然要花费更多的时间。
1、获取SKU的基本信息 0.5s
2、获取SKU的图片信息 0.5s
3、获取SKU的促销信息 1s
4、获取SPU的所有销售属性 1s
5、获取SPU的详情 1.5s
假如商品详情页的每个查询,如果如上标注的时间才能完成,那么用户需要4.5秒的时间,才能够看到商品详情页面的内容,很显然是不能够接受的。
如果有多个线程同时完成这6步操作,也许仅仅1.5秒就能够完成。
4 5 需要1的返回结果。
- //测试异步任务
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- System.out.println("main .... start");
- CompletableFuture
completableFuture = CompletableFuture.runAsync(() -> { - System.out.println("当前线程:" + Thread.currentThread().getId());
- int i = 10 / 2;
- System.out.println("运行结果:" + i);
- }, pool);
-
- System.out.println("main ... end");
- }
没有返回结果的方法调用:
有返回结果的方法调用:无论是否get操作,使用了改操作,就是阻塞式等待。

- CompletableFuture
future = CompletableFuture.supplyAsync(() -> { - System.out.println("当前线程:" + Thread.currentThread().getId());
- int i = 10 / 2;
- System.out.println("运行结果:" + i);
- return i;
- }, pool);
- System.out.println(future.get());
返回结果:

可以理解为多线程同步调用。get方法为阻塞式等待。
- CompletableFuture
future = CompletableFuture.supplyAsync(() -> { - System.out.println("当前线程:" + Thread.currentThread().getId());
- int i = 10 / 2;
- System.out.println("运行结果:" + i);
- return i;
- }, pool).whenComplete((result,exception)->{
- System.out.println("继续上一个线程的执行结果,用同一个线程继续执行");
- System.out.println("result="+result);
- System.out.println("exception="+exception);
- }).exceptionally(excep->{
- return 10; //遭遇到异常的返回结果
- });
- System.out.println(future.get());
- System.out.println("main ... end");
执行结果:

如果,i=10/0的执行结果如下:

总结:
使用whenComplete的回调方法,参数一:返回结果;参数二:异常。但是该方法无法修改返回结果。是执行当前任务的线程继续执行回调方法的任务。
whenCompleteAsync:是执行把whenCompleteAsync这个任务继续提交给线程池来进行执行。
方法不以Async结尾,意味着Action使用相同的线程执行,而Async可能会使用其他线程执行。(如果是使用相同的线程池,也可能会被同一个线程选中执行)
使用exceptionally,如果遭遇到异常,可以修改返回结果的值。
- CompletableFuture
future = CompletableFuture.supplyAsync(() -> { - System.out.println("当前线程:" + Thread.currentThread().getId());
- int i = 10 / 0;
- System.out.println("运行结果:" + i);
- return i;
- }, pool).handle((result,exception)->{
- if(result!=null){
- return result;
- }
- if(exception!=null){
- return 0;
- }
- return 0;
- });
执行结果:

不得到上一步的返回结果,直接异步执行任务。
- CompletableFuture
future = CompletableFuture.supplyAsync(() -> { - System.out.println("当前线程:" + Thread.currentThread().getId());
- int i = 10 / 0;
- System.out.println("运行结果:" + i);
- return i;
- }, pool).thenRunAsync(()->{
- System.out.println("哈哈");
- },pool);
注意:此时,i=10/0 肯定是抛出异常了,但是咱们抛出了异常,所以程序中断;

如果修改异常代码,i=10/2;

如果使用了thenRun,则是用该线程继续执行任务。
得到上一步的返回结果,但是新任务结果不返回。
- CompletableFuture.supplyAsync(() -> {
- System.out.println("当前线程:" + Thread.currentThread().getId());
- int i = 10 / 2;
- System.out.println("运行结果:" + i);
- return i;
- }, pool).thenAccept(res->{
- System.out.println("res="+res);
- });
执行结果:

得到上一步的返回结果,并且返回新任务的结果。
- CompletableFuture
future = CompletableFuture.supplyAsync(() -> { - System.out.println("当前线程:" + Thread.currentThread().getId());
- int i = 10 / 2;
- System.out.println("运行结果:" + i);
- return i;
- }, pool).thenApplyAsync(res -> {
- System.out.println("res=" + res);
- return 8;
- }, pool);
- System.out.println("get===="+future.get());
- System.out.println("main ... end");
执行结果:

两个任务都完成以后,触发一个事件
组合两个future,获取两个future的返回结果,并返回当前任务的返回值;
组合两个future,获取两个future的返回结果,然后处理任务,没有返回值;
runAfterBoth:组合两个future,不需要获取future的返回结果,只需要两个future处理任务完成后,处理该任务。
- CompletableFuture
future01 = CompletableFuture.supplyAsync(() -> { - System.out.println("线程1的ID:" + Thread.currentThread().getId());
- int i = 10 / 2;
- System.out.println("线程1结束:返回结果为" + i);
- return i;
- }, pool);
-
- CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
- System.out.println("线程2的ID:" + Thread.currentThread().getId());
- return "线程2结束";
- }, pool);
-
- //Async加上就是异步,到最后执行;不加就是约等于同步
- future01.runAfterBothAsync(future02,()->{
- System.out.println("runAfterBoth:"+"不要线程1和线程2的返回结果,新开一个独立线程运行,不是在线程池中");
- });

- future01.thenAcceptBothAsync(future02, (res1, res2) -> {
- System.out.println("thenAcceptBothAsync:" + "会获取到线程1和线程2的返回结果,res1=" + res1 + ",res2=" + res2 + ",但是新任务不会返回!");
- }, pool);

- CompletableFuture
- return res1+"----"+res2;
- }, pool);
- System.out.println(future.get().toString());
- System.out.println("main ... end");
执行结果:

- 当两个任务中,任意一个future任务完成的时候,执行该任务。
-
- applyToEither:两个任务有一个任务执行完成,获取它的返回值,处理任务并有新的返回值。
-
- acceptEither:两个任务有一个任务执行完成,获取它的返回值,处理任务,没有返回值。
-
- runAfterEither:两个任务有一个任务执行完成,不需要获取它的返回值,处理任务,并且没有返回值。
- CompletableFuture<Void> allOf = CompletableFuture.allOf(future01, future02, future03);
- allOf.get();
- System.out.println("main ... end");

执行结果:

如果不加线程池,主线程结束,其余线程也会结束掉。其余线程就不打印东西了。所以要想清楚的看到结果,将线程执行放入到线程池中。