知识卡片
回调线程要识别
内容
回调具体在哪个线程执行,取决于三件事:API 是否区分 Async 变体(如 thenApply 与 thenApplyAsync);注册时异步任务是否已完成(若已完成,某些实现会直接内联执行而不切线程);是否显式指定了执行器。Guava、Netty 的例子共同点是回调在触发完成的线程池/IO线程里执行,但不能一概而论。写回调必须显式确认执行线程,处理异常传播和共享状态。
参考来源
- 位置:《Java高并发核心编程.卷2,多线程、锁、JMM、JUC、高并发设计模式》第9章《高并发核心模式之异步回调模式》9.5.3节《ListenableFuture异步任务》、9.6.3节《ChannelFuture的使用》(源文件:_epub-src/OEBPS/Text/chapter289.xhtml、chapter295.xhtml)
- 结论依据:原文给出Guava通过Guava线程池提交Callable任务、再用Futures.addCallback绑定FutureCallback,“当Callable/Runnable异步执行逻辑完成后,就会回调FutureCallback实例的回调方法”;以及Netty的connect()异步提交任务、真正完成后才回调addListener注册的监听器;两例均说明回调在执行异步任务的线程池/IO线程中触发,而非发起调用的原线程,因此推出本卡结论(并结合JDK CompletableFuture官方文档关于Async变体和内联执行的说明修正为更准确的三条件判断)。
- 原始内容:取到了ListenableFuture实例后,通过Futures.addCallback()方法将FutureCallback回调逻辑的实例绑定到ListenableFuture异步任务实例,实现异步执行完成后的回调……connect的异步任务真正执行完成后,future回调监听器会执行。