与同步编程不同,由于大量上下文切换和线程池,异步编程使得ThreadLocal难以使用。
最简单的是……根本不使用ThreadLocals:D
例如,在Project Reactor中,您可以使用ContextAPI:
Mono.just("Hello %s") .delaySubscription(Flowable.timer(1, TimeUnit.SECONDS)) .transform(flux -> Mono.deferWithContext(ctx -> { return flux.doOnNext(greeting -> { // Get it from the Context String userId = ctx.get("userId"); System.out.println(String.format(greeting, userId)); }); }))
// Put something to the Context, e.g. in the web filter .subscriberContext(Context.of("userId", "bsideup")) .block();
|
在Reactor内部,它不使用任何ThreadLocal,也不会暴露于多线程问题。
但是,此API是Reactor特定的,并且未在Reactive Streams规范中定义,并且您不会在RxJava之类的库中找到它。
其他想法:
可以提出一个通用的Scheduler抽象,这样,探测钩子只需要设置一次。直到JDK中出现此类API。
另一种选择是始终在线程上运行所有内容(类似于Netty的想法),但这会严重影响性能。