java.lang.ThreadLocal - 每个Thread如何拥有自己独立初始化的变量副本?

M. *_*bas 2 java thread-local

关于类java.lang.ThreadLocal的javadoc让我感到困惑.他们说每个访问线程局部变量的线程都有自己独立初始化的变量副本.下面是一个示例(不是真实的生活示例),它证明了线程局部变量中保存的变量可以被许多线程共享:

package com.mohamad.test.threadlocal;

import java.util.List;

public class ThreadLocalExample {

    private static final ThreadLocal<List<Integer>> myThreadLocal = new ThreadLocal<List<Integer>>();

    public static List<Integer> get() {
        return (myThreadLocal.get());
    }

    public static void set(List<Integer> value) {
        myThreadLocal.set(value);
    }
}


package com.mohamad.test.threadlocal;

import java.util.ArrayList;
import java.util.List;


public class TestThreadLocal implements Runnable {

    private static List<Integer> MY_TEST_LIST = new ArrayList<Integer>(){
        /** The serialVersionUID */
        private static final long serialVersionUID = -2419885728976816054L;
        {add(1);}
    };


    /* (non-Javadoc)
     * @see java.lang.Runnable#run()
     */
    public void run() {
        ThreadLocalExample.set(MY_TEST_LIST);
        List<Integer> integers = ThreadLocalExample.get();
        integers.remove(0);
        System.out.println(Thread.currentThread().getName() + " finished successfully, The list's size is: "  + ThreadLocalExample.get().size() + "\n");
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        TestThreadLocal thread1 = new TestThreadLocal();
        Thread t1 = new Thread(thread1);
        t1.start();
        TestThreadLocal thread2 = new TestThreadLocal();
        Thread t2 = new Thread(thread2);
        t2.start();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我们运行本例中,java.lang.IndexOutOfBoundsException会因为抛出MY_TEST_LIST由共享thread1thread2.(正如我们所看到的,当thread1和thread2调用set(MY_TEST_LIST)方法时ThreadLocalExample,它调用了ThreadLocal变量的set方法,它没有创建一个独立的本地副本MY_TEST_LIST)

如果有人已经问过这个问题,请给出答案的链接,因为我在谷歌研究时没有发现任何有趣的东西.

问候,

Tom*_*icz 6

一切都好.变量保持在ThreadLocal线程的本地.在您的情况下,它是一个本地的引用,而不是列表本身.每个线程都有自己的引用副本,但所有这些引用都指向同一个位置.换句话说:每个线程可以保持对不同的引用,List但在您的情况下,它们都指向同一个.

如果您希望您的示例有效,则每个ThreadLocal应该指向不同的ArrayList(副本):

myThreadLocal.set(new ArrayList<Integer>(value));
Run Code Online (Sandbox Code Playgroud)

ThreadLocal一切都指向同一个对象并没有太大的意义,因为在这种情况下,你只需要一个单一的,全球可用的参考.