CompletableFurture实战1.md
背景:
由于需要多处查询,以此查询的话比较耗时,当然也可以用定时同步es或者某个中间件然后再查询,本次采用的多线程查询,利用的是CompletableFuture
当然也可以lietflow 只不过比较简单就没有采用框架,顺便也了解下这个怎么用
目标
Title: 整合数据
A->B: 获取数据库数据(同步)
B-->C: 根据数据id获取c端数据(异步)
B-->D: 根据数据id获取d端数据(异步)
B-->E: 根据数据id获取e端数据(异步)
也就是 a发起获取b中的id,然后分别从c 、d 、e中拉取数据,然后再汇总
构思
首先想到的是 supplyAsync是同步返回结果的,runAsync是没有返回结果的
supplyAsync(() -> { return "获取b中的id"; })
接受前面的返回参数为:thenAccept 和 thenAcceptAsync (当然也有很多,本次讨论这两个)这两个方法:一个是在当前线程中执行,另外一个是异步执行。我们选择的是thenAcceptAsync ,毕竟要速度嘛。
我们需要分别获取c,d,e中的数据,所以可以利用 CompletableFuture中 allof方法,对应有个anyof 就是任意一个返回即可,但是我们需要全部返回
CompletableFuture<Void> voidCompletableFuture = supplyAsync(() -> { System.out.println("执行获取b中的id"); return "获取b中的id"; }).thenAcceptAsync(bb -> { allOf(runAsync(() -> { try { //获取c Thread.sleep(10000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println(bb + " " + Thread.currentThread().getName()); }, threadPoolTaskExecutor), runAsync(() -> { try { //获取d Thread.sleep(20000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println(bb + " " + Thread.currentThread().getName()); }, threadPoolTaskExecutor), runAsync(() -> { try { //获取e Thread.sleep(20000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println(bb + " " + Thread.currentThread().getName()); }, threadPoolTaskExecutor)) ; }); System.out.println("执行状态:"+voidCompletableFuture.isDone()); while (!voidCompletableFuture.isDone()) { try { //获取e Thread.sleep(1000); System.out.println("等待执行完成"); } catch (InterruptedException e) { throw new RuntimeException(e); } } System.out.println("执行状态:"+voidCompletableFuture.isDone()); System.out.println("主线程执行位置"); }, threadPoolTaskExecutor)));
执行获取b中的id 执行状态:false 等待执行完成 执行状态:true 主线程执行位置
这时候发现,并不是我想要的,
1. 将 thenAcceptAsy改成 同步的thenAccep可以吗?如下所示不行
执行获取b中的id 执行状态:true 执行状态:true 主线程执行位置
2. 所以我们将注意放到thenAcceptAsync方法中,其实就是带Async就想new Thread一样,不带就在当前Thread里面执行,但是我们内部用的CompletableFurture.allOf()方法,相当于在方法体内创建一个几个线程来执行,没有同步只等他们执行完。我们在allof()方法后面增加.get()方法,
执行获取b中的id 执行状态:false 等待执行完成 .... 获取b中的id threadPoolTaskExecutor-1 等待执行完成 .... 获取b中的id threadPoolTaskExecutor-2 获取b中的id threadPoolTaskExecutor-3 等待执行完成 执行状态:true 主线程执行位置
3. 综上所述,在CompletableFurture中提供的方法返回的furture对象,如果在内部开启了线程除非同步等待内部执行完成如.get()方法或者.join()方法,否者该对象完成是不包含内部线程池的内容,相当于把任务丢给别了就拉到了, 想必如果只是几个thread在一起掺和还可以分得清,但是换一种模式就不太好理解了