回调桥接 Future解决的问题 可以异步等待 Future是一个占位符,代表"未来某个时刻才有的结果" // 同步 —— 卡在这行,等结果回来才往下走 String result= blockingCall ( ) ; // 异步 —— 立刻返回一个"凭证"(Future),实际结果稍后才就绪 Future < String > ticket= asyncCall ( ) ; // ... 你可以先做其他事 ... String result= ticket. get ( ) ; // 这里才真正等 Future的问题 Future < String > f= executor. submit ( ( ) -> "hello" ) ; // 硬伤 1:只能阻塞等,没法说"好了之后自动帮我做下一步" f. get ( ) ; // 阻塞当前线程 // 硬伤 2:没法手动把一个值放进去(只能靠线程执行完自动填) executor.submit是指把括号里里面的任务提交给线程池子,线程池安排一个线程异步执行 一个问题是当我get()结果的时候,如果没有执行完的话会阻塞在这个地方 问题二是指有办法主动往 Future 里塞一个结果,结果只能等线程池里的任务跑完自动填入 比如这种情况就要主动填入 // 假设你已经知道结果,想直接包成 Future 返回 public Future < String > getData ( ) { if ( cacheHit) { // 想直接返回结果,不走线程池 // Future 做不到!没有办法手动填值 } return executor. submit ( ( ) -> fetchFromDB ( ) ) ; } CompletableFuture解决了手动填值和链式编排 // 你可以在任何时刻、任何地方,把结果"塞"进去 f. complete ( "结果来了" ) ; // 或者塞一个异常 f. completeExceptionally ( new RuntimeException ( "出错了" ) ) ; CompletableFuture < String > f= CompletableFuture . supplyAsync ( ( ) -> "hello" ) ; // 不阻塞,而是注册"好了之后做什么" f. thenApply ( s-> s+ " world" ) // hello → hello world . thenApply ( s-> s. toUpperCase ( ) ) // → HELLO WORLD . thenAccept ( result-> System . out. println ( result) ) ; // 自动触发,不用手动 get langchian4j里面为什么要Future 需要Future的场景是:你要等回调结果,然后用这个结果做下一步 因为流式输出是回调实现的 回调是一次性的、嵌套的、难以组合的,而 Future 是可等待的、可链式的、可组合的。翻译一次,后续编排就从"痛苦"变成"自然" 给我印象最深刻的例子:先生成大纲然后写正文 model. chat ( 大纲请求, new StreamingChatResponseHandler ( ) { @Override public void onCompleteResponse ( ChatResponse outline) { // 第一步完成了,现在发起第二步 model. chat ( 正文请求( outline) , new StreamingChatResponseHandler ( ) { @Override public void onCompleteResponse ( ChatResponse body) { // 第二步完成了,现在发起第三步 model. chat ( 摘要请求( body) , new StreamingChatResponseHandler ( ) { @Override public void onCompleteResponse ( ChatResponse summary) { // 终于拿到最终结果了…… // 三层嵌套,还想继续加?四层、五层…… } @Override public void onError ( Throwable error) { . . . } } ) ; } @Override public void onError ( Throwable error) { . . . } } ) ; } @Override public void onError ( Throwable error) { . . . } } ) ; CompletableFuture < String > result= callLLM ( 大纲请求) . thenCompose ( outline-> callLLM ( 正文请求( outline) ) ) . thenCompose ( body-> callLLM ( 摘要请求( body) ) ) ; // 逻辑是一条线,从上往下读 // 错误处理可以统一在最后 result. exceptionally ( error-> "出错了: " + error. getMessage ( ) ) ; 并行编排 并行调用ai的正确方法 // ✅ 正确:先全部发射 var f1= askStream ( model, q1) ; // 网络请求已经发出,线程去等响应了 var f2= askStream ( model, q2) ; // 第二个请求立刻发出,不用等 f1 回来 var f3= askStream ( model, q3) ; // 第三个也立刻发出 // 然后才统一等待结果 String a1= f1. join ( ) ; // 如果 f1 已经回来了,瞬间拿到;没回来就等 String a2= f2. join ( ) ; String a3= f3. join ( ) ;