Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么ThreadLocal变量需要静态?_Java_Multithreading - Fatal编程技术网

Java 为什么ThreadLocal变量需要静态?

Java 为什么ThreadLocal变量需要静态?,java,multithreading,Java,Multithreading,我读过很多关于为什么ThreadLocal变量需要是静态的文章(虽然不是必需的),但我不明白为什么它应该是静态的 我读过它和许多其他链接,但没有想到 我做过类似的事情 public class ThreadLocalDemo{ public static void main(String[]args)throws Exception{ SharedRersource r1= new SharedRersource(); Thread t1= new Th

我读过很多关于为什么
ThreadLocal
变量需要是静态的文章(虽然不是必需的),但我不明白为什么它应该是静态的

我读过它和许多其他链接,但没有想到

我做过类似的事情

public class ThreadLocalDemo{

    public static void main(String[]args)throws Exception{
        SharedRersource r1= new SharedRersource();
        Thread t1= new Thread(r1);
        Thread t2= new Thread(r1);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("Main thread Exiting...");
        }

    }

class SharedRersource implements Runnable{


        private ThreadLocal<Integer> threadId = new ThreadLocal(){
            protected Integer initialValue(){
                return (int)(Math.random()*100);
                }
        };
        public void run(){

            try{
                Thread.sleep(2000);
            }
            catch(InterruptedException e){
                e.printStackTrace();
                }
                System.out.println(threadId.get());

            }
        };
public类ThreadLocalDemo{
公共静态void main(字符串[]args)引发异常{
SharedResource r1=新的SharedResource();
螺纹t1=新螺纹(r1);
螺纹t2=新螺纹(r1);
t1.start();
t2.start();
t1.join();
t2.连接();
System.out.println(“主线程退出…”);
}
}
类SharedResource实现可运行{
private ThreadLocal threadId=new ThreadLocal(){
受保护的整数初始值(){
返回值(int)(Math.random()*100);
}
};
公开募捐{
试一试{
《睡眠》(2000年);
}
捕捉(中断异常e){
e、 printStackTrace();
}
System.out.println(threadId.get());
}
};
这里线程t1和t2拥有threadId的私有副本,而不是为什么它应该是静态的

请给我一个更好的理解。
感谢您的实现,您(逻辑上)拥有了
threadID
的4个不同实例:

  • r1.threadID{t1}
    -实例保存在资源
    r1
    中,由线程
    t1
    观察。如果中断,它将通过线程
    t1
    打印

  • r2.threadID{t2}
    -实例保存在资源
    r2
    中,由线程
    t2
    观察。如果中断,它将通过线程
    t2
    打印

  • r1.threadID{t2}
    -实例保存在resource
    r1
    中,在case中由线程
    t2
    观察,例如,如果它(直接)调用
    r1.run()

  • r2.threadID{t2}
    -实例保存在resource
    r2
    中,由线程
    t1
    在case中观察,例如,如果它(直接)调用
    r2.run()

  • 您不太可能需要第三个和第四个实例,因此您可以:

    • 使变量为静态
    在这种情况下,您将有两个实例:
    threadID{t1}
    ,由thread
    t1
    观察,和
    threadID{t2}
    ,由thread
    t2
    观察

    • 将变量设为非ThreadLocal
    在这种情况下,您将有两个实例:
    r1.threadID
    ,通过
    r1
    (通过thread
    t1
    )观察;和
    r2.threadID
    ,通过
    r2
    (通过thread
    t2
    )观察。

    ThreadLocal
    变量需要是静态的,没有内在原因。只是,
    ThreadLocal
    解决的问题通常只发生在基于static-y设计思想的程序中

    在我看来,您最有可能在最初是单线程的代码中找到
    ThreadLocal
    ,直到有人将其“升级”为使用多线程。当大量代码最初引用某个静态变量时,线程局部就很方便了,现在您需要在同一代码体中运行的每个线程都有自己的副本


    在我看来,
    ThreadLocal
    是一种代码气味——一种糟糕设计的标志。一个设计良好的多线程程序不需要它。

    A
    ThreadLocal
    不需要是静态的。就像其他变量一样,它取决于您的意图:

    public class FooClass {
      static Integer staticVar                          // 1 per process
      Integer var;                                      // 1 per instance
    
      static ThreadLocal<Integer> staticThreadLocalVar; // 1 per thread
      ThreadLocal<Integer> threadLocalVar;              // 1 per thread per instance
    }
    
    公共类{
    静态整数staticVar//1每个进程
    整型变量;//每个实例1
    static ThreadLocal staticThreadLocalVar;//每个线程1
    ThreadLocal threadLocalVar;//每个实例每个线程1个
    }
    
    你所给的报价正是指上面列出的第三个案例

    ThreadLocal实例通常是类中的私有静态字段 希望将状态与线程关联的


    但是,在某些情况下,将状态与每个实例的线程相关联可能是完全合理的,在这种情况下,您可能希望使用
    非静态
    ThreadLocal
    (第四种情况)。

    这个问题的答案取决于ThreadLocal实现

    将ThreadLocal视为一个容器

    ThreadLocal
    是一个在内部维护
    ThreadLocalMap
    的容器,这
    ThreadLocalMap
    是ThreadLocal需要保持静态的关键(虽然不是必需的,但建议保持静态)

    因为我们希望
    每个类有一个容器
    而不是每个实例有一个容器
    。如果我们每个实例有一个容器,我们将拥有和实例一样多的容器,这将造成内存泄漏。

    这里有更多细节


  • 您链接的问题的答案很好地解释了这一点。你还不明白什么?您是否了解,如果您有10个对象,每个对象都有一个ThreadLocal实例字段,那么您有10个不同的位置,其中一些状态可以与当前线程关联?你通常不希望这样。您通常想要的是类似“当前使用此线程的用户是John”或“与当前线程关联的事务就是该线程”的内容。从技术上讲,它不必是,但是你能说出一件你不希望它是静态的东西吗?@Voo:问题是我刚刚看到SpringSecurity ContextHolder类,其中身份验证对象保存在ThreadLocal变量中。所以要理解这一点,我需要理解ThreadLocal变量