"withInitial" 与 "InitialValue" 在 threadLocal 中
"withInitial" vs "InitialValue" In threadLocal
我对 threadLocal 的 initialValue 和 withInital 方法有点困惑。
考虑一种情况,我在父线程中有数据,我正在使用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());
}
}
}
输出:
Parent Thread Value : parent data
Child Thread Value : parent data
我在父线程中创建线程,并调用子线程。子线程正在从父线程继承数据。
现在,如果我像这样初始化变量 data
(在第 2 行中):
public static ThreadLocal<String> data =InheritableThreadLocal.withInitial(() -> "temp");
我得到以下输出:
Parent Thread Value :parent data
Child Thread Value :temp
我不确定为什么会这样。我阅读了oracle的文档,但没有得到有用的东西。
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--
我想知道如何使用 withInitial
而不是使用 initialValue
获得相同的输出?
withInitial
不会创建 InheritableThreadLocal
。它只会创建一个常规的 ThreadLocal
,这就是为什么您会在输出中看到 temp
。
withInitial
是一个静态方法,所以它不能被 InheritableThreadLocal
覆盖以做一些不同的事情,比如 returning 一个 InheritableThreadLocal
.
所以你不能做同样的事情,但是 withInitial
,因为它 return 不是你需要的对象类型。
如另一个答案中所述,withInitial
定义在 ThreadLocal
和 returns 中 SuppliedThreadLocal
类型的对象扩展 ThreadLocal
而不是InheritableThreadLocal
。由于 JDK 中没有定义(还?)这样的静态工厂方法,您可以创建自己的可继承实用程序版本:
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");
我对 threadLocal 的 initialValue 和 withInital 方法有点困惑。
考虑一种情况,我在父线程中有数据,我正在使用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());
}
}
}
输出:
Parent Thread Value : parent data
Child Thread Value : parent data
我在父线程中创建线程,并调用子线程。子线程正在从父线程继承数据。
现在,如果我像这样初始化变量 data
(在第 2 行中):
public static ThreadLocal<String> data =InheritableThreadLocal.withInitial(() -> "temp");
我得到以下输出:
Parent Thread Value :parent data
Child Thread Value :temp
我不确定为什么会这样。我阅读了oracle的文档,但没有得到有用的东西。 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--
我想知道如何使用 withInitial
而不是使用 initialValue
获得相同的输出?
withInitial
不会创建 InheritableThreadLocal
。它只会创建一个常规的 ThreadLocal
,这就是为什么您会在输出中看到 temp
。
withInitial
是一个静态方法,所以它不能被 InheritableThreadLocal
覆盖以做一些不同的事情,比如 returning 一个 InheritableThreadLocal
.
所以你不能做同样的事情,但是 withInitial
,因为它 return 不是你需要的对象类型。
如另一个答案中所述,withInitial
定义在 ThreadLocal
和 returns 中 SuppliedThreadLocal
类型的对象扩展 ThreadLocal
而不是InheritableThreadLocal
。由于 JDK 中没有定义(还?)这样的静态工厂方法,您可以创建自己的可继承实用程序版本:
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");