owner
owner copied to clipboard
Unable to ThreadLocal ConfigCache.getOrCreate()
owner version: 1.0.12
Use case
I have a scenario where:
- I first create my config in the Owner supported way:
@LoadPolicy(LoadType.MERGE)
@Sources({"system:properties", "classpath:tests.properties"})
public interface Config extends Mutable {
@Key("prop")
String prop();
}
- But later at runtime I need to replace existing properties with new values.
So that when I'm running multi-thread, I start with the same set of properties, And each thread replaces properties at their own pace.
Roughly speaking I need to maintain an isolated instance of the config for each thread. But at the same time I don't want to create a new instance of my config within each thread.
Problem description
Documentation says that ConfigCache.getOrCreate
is a thread-safe Singleton.
So I tried to instantiate my ConfigCache.getOrCreate
as a ThreadLocal<Config>
.
But my tests show that I'm unable to make it ThreadLocal at all. All the threads still get access to the same instance of the config.
Example
public class AppShort {
public static void main(String[] args) {
new Thread(() -> useConfig()).start();
new Thread(() -> useConfig()).start();
}
private static void useConfig() {
ThreadLocal<Config> threadLocalConfig = ThreadLocal.withInitial(() -> ConfigCache.getOrCreate(Config.class));
System.out.println(Thread.currentThread().getName() + ": Current config id: " + System.identityHashCode(threadLocalConfig.get()));
System.out.println(Thread.currentThread().getName() + ": Replacing property in config");
String propOld = threadLocalConfig.get().setProperty("prop", Thread.currentThread().getName());
System.out.println(Thread.currentThread().getName() + ": Replaced property, old value: " + propOld + ", new value: " + threadLocalConfig.get().prop());
}
}
Execute
Running with -Dprop=origValue
gives me this output:
Thread-2: Current config id: 1423910510
Thread-1: Current config id: 1423910510
Thread-2: Replacing property in config
Thread-1: Replacing property in config
Thread-2: Replaced property, old value: origValue, new value: Thread-1
Thread-1: Replaced property, old value: Thread-2, new value: Thread-1
We can see the same config Id is obtained in both threads.
Question
Is this by design or there still any way to make ConfigCache.getOrCreate()
thread-isolated?
Workaround
I have to just use ConfigFactory.create()
and wrap it into a Singleton myself inside each thread.
I don't have to wrap it into ThreadLocal and getting different config objects inside each thread by default.
Nice to have
It would be great if I could just use ConfigCache.getOrCreate()
isolated inside each of my threads.