Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"withInitial" vs "InitialValue" In threadLocal

I am bit confused between initialValue vs withInital method for threadLocal.

Consider a situation, I have data in parent thread, and I am using InheritableThreadLocal.

public class Parent extends Thread {
public static ThreadLocal<String> data = new InheritableThreadLocal<String>() {
    @Override
    protected String initialValue() {
        return "temp";
    }
};

public static void main(String[] args) {
    new Parent().start();
}

public void run() {
    data.set("parent data");
    System.out.println("Parent Thread Value :" + data.get());
    new ChildThread().start();
}

class ChildThread extends Thread {
    public void run() {
        System.out.println("Child Thread Value :" + Parent.data.get());
    }
}
}

Output:

Parent Thread Value : parent data
Child Thread Value : parent data

I am creating thread in parent, and calling child thread. The child is inheriting data from parent thread.

Now if I initialize variable data (In line 2) like this:

public static ThreadLocal<String> data =InheritableThreadLocal.withInitial(() -> "temp");

I get the following output:

Parent Thread Value :parent data
Child Thread Value :temp

I am not sure why its happening. I read oracle's document, but didn't get something useful. https://docs.oracle.com/javase/8/docs/api/java/lang/ThreadLocal.html#withInitial-java.util.function.Supplier- https://docs.oracle.com/javase/8/docs/api/java/lang/ThreadLocal.html#initialValue--

I wonder how can I achieve the same output with withInitial instead of using initialValue?

like image 630
Prateek Agrawal Avatar asked Apr 18 '26 04:04

Prateek Agrawal


2 Answers

withInitial does not create an InheritableThreadLocal. It only creates a regular ThreadLocal, which is why you see temp in the output.

withInitial is a static method, so it can't be overridden by InheritableThreadLocal to do something different instead, like returning an InheritableThreadLocal.

So you can't do the same thing, but with withInitial, because it doesn't return the type of object you need.

like image 139
Sweeper Avatar answered Apr 19 '26 17:04

Sweeper


As mentioned in the other answer, withInitial is defined in ThreadLocal and returns an object of a type SuppliedThreadLocal that extends ThreadLocal and not InheritableThreadLocal. Since such a static factory method is not defined (yet?) in the JDK, you can create your own inheritable utility version:

static final class SuppliedInheritableThreadLocal<T> extends InheritableThreadLocal<T> {

    private final Supplier<? extends T> supplier;

    SuppliedInheritableThreadLocal(Supplier<? extends T> supplier) {
        this.supplier = Objects.requireNonNull(supplier);
    }

    @Override
    protected T initialValue() {
        return supplier.get();
    }

    public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) {
        return new SuppliedInheritableThreadLocal<>(supplier);
    }
}

public static ThreadLocal<String> data = SuppliedInheritableThreadLocal.withInitial(() -> "temp");
like image 40
M A Avatar answered Apr 19 '26 17:04

M A