【问题标题】:ThreadLocal and list doesn't workThreadLocal 和列表不起作用
【发布时间】:2013-09-05 08:08:03
【问题描述】:

我的基于 ThreadLocal 的类有问题。任何帮助,将不胜感激。这是一个带有简单列表的基类:

public class ThreadLocalTest {

protected static final ThreadLocal<List<String>> thList = new ThreadLocal<List<String>>() {
    protected List<String> initialValue() {
        return new ArrayList<String>();
    }
};

public static void put(String k) {
    thList.get().add(k);
}

public static List<String> getList() {
    return thList.get();
}

}

我是这样测试的:

Thread th1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("------------------thread1---------------------------");
                ThreadLocalTest.put("a");
                ThreadLocalTest.put("b");
                List<String> l = ThreadLocalTest.getList();
                System.out.println(l.size());
                System.out.println("----------------------------------------------------");
            }
        });
        Thread th2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("------------------thread2---------------------------");
                ThreadLocalTest.put("c");
                List<String> l = ThreadLocalTest.getList();
                System.out.println(l.size());
                System.out.println("----------------------------------------------------");
            }
        });
        th1.run();
        th2.run();
        th1.run();
        th2.run();
        th1.run();
        th2.run();
        th1.run();
        th2.run();

所以我得到的是:

------------------thread1---------------------------
2
----------------------------------------------------
------------------thread2---------------------------
3
----------------------------------------------------
------------------thread1---------------------------
5
----------------------------------------------------
------------------thread2---------------------------
6
----------------------------------------------------
------------------thread1---------------------------
8
----------------------------------------------------
------------------thread2---------------------------
9
----------------------------------------------------
------------------thread1---------------------------
11
----------------------------------------------------
------------------thread2---------------------------
12
----------------------------------------------------

您看到这些线程似乎实际上共享同一个列表,但我不明白为什么。

有什么建议吗?

【问题讨论】:

  • 为什么你期望你的线程在不同的线程中运行?在循环中使用 new Thread1().start() 或类似的东西,你会看到预期的结果。

标签: java thread-safety thread-local


【解决方案1】:

您调用run() 方法而不是start()run() 在调用它的同一线程中运行,而start() 在新的单独线程中调用run()。实际上,您所有的“线程”都在同一个线程中执行。

【讨论】:

    【解决方案2】:

    这里有两个问题。

    1) 您不能通过直接调用run 方法来执行新的Thread。这跳过了“魔术”,只在主线程中调用 run 方法。结果,您所看到的一切都发生在同一个线程中,因此只有一个 ThreadLocal 列表。

    要使新的Thread 执行,您必须调用start

    2) 你不能在同一个Thread 上多次调用'start',所以你不能测试你正在尝试的多次调用。您每次都必须创建新的 Thread 对象,但这意味着它们显然不共享 ThreadLocal 变量,我猜您正在尝试测试

    【讨论】:

    • 他已经创建了一个线程。并且线程不是通过调用 start 创建的。已创建的 Thread 对象在其 start() 方法被调用时开始运行。此外,可以多次调用start() - 但结果不会是 OP 所期望的。我知道你的意思,但请准确。
    • 谢谢。在我看来,非执行线程不是线程,但你是对的,这不是真的!
    【解决方案3】:

    您看到这些线程似乎实际上共享相同的列表,但我不明白为什么。

    原因是您实际上并没有创建任何新线程。您的所有代码都使用主线程运行(因此,您看到的行为完全符合预期)。

    你需要启动新的执行线程运行:

    替换:

    th1.run();
    th2.run();
    th1.run();
    th2.run();
    th1.run();
    th2.run();
    th1.run();
    th2.run();
    

    与:

    th1.start();
    th2.start();
    

    但是,在尝试解释您的输出时要小心。由于线程将同时运行,因此对控制台的写入可能是混合的。

    【讨论】:

      【解决方案4】:

      并且您不能在启动后启动同一个 Thread 对象,您必须重新创建它。

      【讨论】:

        猜你喜欢
        • 2021-09-07
        • 1970-01-01
        • 1970-01-01
        • 2016-10-30
        • 2021-02-07
        • 2022-06-10
        • 2015-01-08
        • 2018-05-30
        • 1970-01-01
        相关资源
        最近更新 更多