-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
讨论:Session级Cache场景下,TransmittableThreadLocal的使用 #122
Labels
Comments
『Cache的问题』 与 『TTL的传递问题』是正交的。 表述如下: @olove 设计表述在设计上/思路/概念上,
实现上的注意点
代码表述对应你的Demo代码,调整后,用代码表述如下: import com.alibaba.ttl.TransmittableThreadLocal;
import com.alibaba.ttl.TtlRunnable;
import io.reactivex.Flowable;
import io.reactivex.functions.Consumer;
import io.reactivex.plugins.RxJavaPlugins;
import io.reactivex.schedulers.Schedulers;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ThreadLocalRandom;
public class SessionCacheDemo {
@BeforeClass
public static void beforeClass() {
// RxJava 集成 TTL
RxJavaPlugins.setScheduleHandler(TtlRunnable::get);
}
@Test
public void getSomethingByCache() throws Exception {
BizService bizService = new BizService();
final Consumer<Object> printer = result -> System.out.printf("[%30s]: %s%n", Thread.currentThread().getName(), bizService.getCache());
Flowable.just(bizService)
.observeOn(Schedulers.io())
.map(BizService::getItemByCache)
.doOnNext(printer)
.blockingSubscribe(printer);
// 业务 在后续时刻 需要用到
Object object = bizService.getItemByCache();
printer.accept(object);
}
/**
* Mock Service
*/
private static class BizService {
private static final String ONLY_KEY = "ONLY_KEY";
private final TransmittableThreadLocal<ConcurrentMap<String, Item>> cache_context = new TransmittableThreadLocal<ConcurrentMap<String, Item>>() {
@Override
protected ConcurrentMap<String, Item> initialValue() {
return new ConcurrentHashMap<>(); // init cache
}
};
public BizService() {
// NOTE: AVOID cache object lazy init
cache_context.get();
}
public Item getItem() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// do nothing
}
return new Item(ThreadLocalRandom.current().nextInt(0, 10_000));
}
/**
* 获取业务数据,一般使用spring cache做缓存,这里简单实现
*/
public Item getItemByCache() {
final ConcurrentMap<String, Item> cache = cache_context.get();
return cache.computeIfAbsent(ONLY_KEY, key -> getItem());
}
public Item getCache() {
return cache_context.get().get(ONLY_KEY);
}
public void clearCache() {
cache_context.get().clear();
}
}
/**
* Mock Cache Data
*/
public static class Item {
private int id;
public Item(int id) {
this.id = id;
}
@Override
public String toString() {
return "Item{id=" + id + '}';
}
}
} 运行结果[ RxCachedThreadScheduler-1]: Item{id=248}
[ main]: Item{id=248}
[ main]: Item{id=248} |
转成 transmittable-thread-local/src/test/java/com/alibaba/demo/session_cache/SessionCacheDemo.kt Lines 31 to 45 in b0854e7
运行结果: [ pool-1-thread-2] cache: Item(id=9335)
[ main] cache: Item(id=9335)
[ main] cache: Item(id=9335)
[ RxCachedThreadScheduler-1] cache: Item(id=8624)
[ main] cache: Item(id=8624)
[ main] cache: Item(id=8624) 感谢 @olove 场景说明 与 示例(代码)提供! ❤️ |
谢谢@oldratlee 这么详细的说明和demo用例 |
oldratlee
changed the title
TransmittableThreadLocal不支持子线程往父线程透传新增threadLocal值
Session级Cache场景下,TransmittableThreadLocal的使用问题
Nov 30, 2018
Closed
oldratlee
changed the title
Session级Cache场景下,TransmittableThreadLocal的使用问题
讨论:Session级Cache场景下,TransmittableThreadLocal的使用
Aug 26, 2019
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
场景
某些业务流程计算逻辑复杂,基础数据读取服务可能需要多次调用。
希望做线程级缓存(更准确地说,因为涉及多个上下游线程,其实是Session级的缓存),避免重复调用外部服务。
问题
数据产生可能来源于子线程,
TransmittableThreadLocal
在copy
数据的时候,忽略主线程不存在的key
,导致主线程无法读取到子线程新创建的ThreadLocal
值。解决方案
TransmittableThreadLocal
可以增加参数控制是否需要向父线程传递新增ThreadLocal
。示例代码
The results:
The text was updated successfully, but these errors were encountered: