2

我的基于 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
----------------------------------------------------

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

有小费吗?

4

4 回答 4

5

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

于 2013-09-05T08:10:15.397 回答
2

这里有两个问题。

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

要使 newThread执行,您必须调用start

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

于 2013-09-05T08:24:16.487 回答
1

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

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

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

代替:

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

和:

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

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

于 2013-09-05T08:11:50.657 回答
0

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

于 2013-09-05T08:24:02.940 回答