ThreadLocal难以在异步编程或Reactive编程中使用 - bsideup

20-02-26 banq

与同步编程不同,由于大量上下文切换和线程池,异步编程使得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的想法),但这会严重影响性能。