【问题标题】:"withInitial" vs "InitialValue" In threadLocalthreadLocal 中的“withInitial”与“InitialValue”
【发布时间】:2021-09-27 04:55:36
【问题描述】:

我对 threadLocal 的 initialValuewithInital 方法有点困惑。

考虑一种情况,我在父线程中有数据,我正在使用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 将返回 ThreadLocal,因为它是 ThreadLocal 上的工厂方法,而不是 InheritableThreadLocal 上的工厂方法。但是它从InheritableThreadLocal 可见,因为它扩展了ThreadLocal

标签: java multithreading java-8 thread-local inheritable-thread-local


【解决方案1】:

withInitial 不会创建 InheritableThreadLocal。它只会创建一个常规的ThreadLocal,这就是为什么您会在输出中看到temp

withInitial 是一个静态方法,因此它不能被 InheritableThreadLocal 覆盖以执行不同的操作,例如返回 InheritableThreadLocal

所以你不能用withInitial做同样的事情,因为它不会返回你需要的对象类型。

【讨论】:

  • 当然,InheritableThreadLocal 可以声明自己的withInitial 方法。它只是没有。很可能,因为为从不继承值的可继承线程局部变量提供工厂几乎没有意义。
【解决方案2】:

正如另一个答案中提到的,withInitialThreadLocal 中定义,并返回一个扩展ThreadLocal 而不是InheritableThreadLocalSuppliedThreadLocal 类型的对象。由于在 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");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-24
    • 2014-03-20
    • 2016-08-28
    • 1970-01-01
    • 2012-10-26
    相关资源
    最近更新 更多