【问题标题】:why doesn't my initialValue() of ThreadLocal work?为什么我的 ThreadLocal 的 initialValue() 不起作用?
【发布时间】:2017-12-28 09:15:12
【问题描述】:

我想在 java 中测试 ThreadLocal 对象的用法,但似乎我的 initialValue() 不起作用。我实际上在set() 之前调用了get(),它应该返回变量ID,如预期的那样为100。这是我的代码:

public class UsageThreadLocal implements Runnable {
    private AnotherThreadID<Long> var;

    public UsageThreadLocal(AnotherThreadID<Long> v) {
        this.var = v;
    }

    public void run() {
        try {
            print("var getThreadID =" + var.get());
            Thread.sleep(200);
            var.set(Thread.currentThread().getId());
            print("var getThreadID =" + var.get());
        } catch (InterruptedException x) {
        }
    }

    private static void print(String msg) {
        String name = Thread.currentThread().getName();
        System.out.println(name + ": " + msg);
    }

    public static void main(String[] args) {
        AnotherThreadID<Long> tid = new AnotherThreadID<Long>() {
            @Override
            public Long initialValue() {
                ID = new Long(100);
                System.out.println("I'm in initialValue()!");
                return ID;
            }
        };
        UsageThreadLocal shared = new UsageThreadLocal(tid);

        try {
            Thread threadA = new Thread(shared, "threadA");
            threadA.start();

            Thread.sleep(50);

            Thread threadB = new Thread(shared, "threadB");
            threadB.start();

            Thread.sleep(50);

            Thread threadC = new Thread(shared, "threadC");
            threadC.start();
        } catch (InterruptedException x) {
        }
    }
}

class AnotherThreadID<T> extends ThreadLocal<T> {
    public T ID;

    @Override
    public void set(T newID) {
        ID = newID;
    }

    @Override
    public T get() {
        return ID;
    }

}

和我的代码的执行结果:

threadA: var getThreadID =null
threadB: var getThreadID =null
threadC: var getThreadID =null
threadA: var getThreadID =9
threadB: var getThreadID =10
threadC: var getThreadID =11

我的代码有什么问题还是我误解了ThreadLocal的用法?

【问题讨论】:

  • 所有对象自动继承Object,无需显式扩展(extends Object)

标签: java multithreading initialization thread-local


【解决方案1】:

问题在于AnotherThreadID 的实现。 ThreadLocal 是为每个线程保留一个值,你覆盖 get()set() 基本上使它不再是 ThreadLocal

您可以删除AnotherThreadID 类,并将所有AnotherThreadID 替换为ThreadLocal,然后您的代码无需进一步更改即可工作。

【讨论】:

  • 谢谢@Kevin Wang。行得通,也就是说覆盖get()set()需要更复杂的工作吗?
  • @zhanghui 通常实现initialValue() 就足够了。如果您看一下 ThreadLocal 中的 get() 和 set(),您会更好地了解它是如何工作的。老实说,我不知道在什么情况下需要覆盖它们。
  • 这意味着我应该将get()set() 视为在MyThreadLocal 对象中构建我想要的行为的基本方法?
  • 没有简单的规则说应该或不应该覆盖这两种方法。这真的取决于您的应用程序。
【解决方案2】:

AnotherThreadID 应该是由它的线程初始化的,但是你在主线程中初始化它。而且你只有一个AnotherThreadID实例。实际上,每个线程都应该有一个实例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-27
    • 1970-01-01
    • 2015-09-25
    • 2018-03-05
    • 2013-04-19
    • 2015-10-17
    • 2016-02-20
    相关资源
    最近更新 更多