简体   繁体   English

为什么ThreadLocal变量需要静态?

[英]Why ThreadLocal variable need to static?

I have read many articles on why ThreadLocal variable need to be static(although not necessary), but I didn't get the idea why it should be static. 我已经阅读了许多关于为什么ThreadLocal变量需要是静态的文章(尽管没有必要),但我不明白为什么它应该是静态的。

I have read it here and many other links but didn't get the idea. 我在这里阅读了许多其他链接,但没有得到这个想法。

I have done something like this 我做过这样的事情

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());

            }
        };

Here thread t1 and t2 is having private copy of threadId than why It should be static 这里线程t1和t2具有threadId的私有副本,而不是为什么它应该是静态的

Please give a better understanding to me. 请更好地了解我。 Thanks 谢谢

Answer to this question lies into ThreadLocal implementation . 这个问题的答案在于ThreadLocal的实现。

Think ThreadLocal as a container 将ThreadLocal视为容器

ThreadLocal is a container that maintain a ThreadLocalMap internally , This ThreadLocalMap is the key why threadlocal need to be static(although not necessary ,but suggestion is keep it static). ThreadLocal是,保持容器ThreadLocalMap内部 ,这ThreadLocalMap的关键是为什么ThreadLocal的需要是静态的(虽然不是必须的,但建议是保持它的静态)。

Because we want single container per class , not container per instance .If we have container per instance we will be having as many container as instance and that will created memory leak . 因为我们想要single container per classnot container per instance 。如果我们not container per instance都有容器,那么我们将拥有与实例一样多的容器,这将产生内存泄漏。

More detail here 更多细节在这里

  1. http://www.0xcafefeed.com/2004/06/of-non-static-threadlocals-and-memory/ http://www.0xcafefeed.com/2004/06/of-non-static-threadlocals-and-memory/
  2. https://www.appneta.com/blog/introduction-to-javas-threadlocal-storage/ https://www.appneta.com/blog/introduction-to-javas-threadlocal-storage/

With your implementation you have (logically) 4 different instances of threadID : 通过您的实现,您(逻辑上)有4个不同threadID 实例

  1. r1.threadID{t1} - Instance saved in resource r1 and observed by thread t1 . r1.threadID{t1} - 保存在资源r1并由线程t1观察的实例。 It will be printed by thread t1 if it will be interrupted. 如果它被中断,它将由线程t1打印。

  2. r2.threadID{t2} - Instance saved in resource r2 and observed by thread t2 . r2.threadID{t2} - 保存在资源r2并由线程t2观察的实例。 It will be printed by thread t2 if it will be interrupted. 如果它被中断,它将由线程t2打印。

  3. r1.threadID{t2} - Instance saved in resource r1 and observed by thread t2 in case, eg, if it calls (directly) r1.run() . r1.threadID{t2} - 实例保存在资源r1并由线程t2观察,例如,如果它(直接)调用r1.run()

  4. r2.threadID{t2} - Instance saved in resource r2 and observed by thread t1 in case, eg, if it calls (directly) r2.run() . r2.threadID{t2} - 保存在资源r2并由线程t1观察的实例,例如,如果它(直接)调用r2.run()

It is unlikely that you need 3-rd and 4-th instances, so you may: 您不太可能需要第3和第4个实例,因此您可以:

  • Make variable static . 使变量静态

In that case you will have two instances : threadID{t1} , which is observed by thread t1 , and threadID{t2} , which is observed by thread t2 . 在这种情况下,您将有两个实例 :由线程t1观察到的threadID{t1}和由线程t2观察到的threadID{t2}

  • Make variable non-ThreadLocal . 使变量非ThreadLocal

In that case you will have two instances : r1.threadID , which is observed via r1 (by thread t1 ), and r2.threadID , which is observed via r2 (by thread t2 ). 在这种情况下,您将有两个实例r1.threadID ,通过r1 (通过线程t1 )观察到, r2.threadID ,通过r2 (通过线程t2 )观察到。

There is no inherent reason why a ThreadLocal variable needs to be static. ThreadLocal变量需要是静态的,没有固有的原因。 It's just that, the problem that ThreadLocal solves is a problem that usually only occurs in programs that are based on static-y design ideas. 就是这样, ThreadLocal解决的问题通常只发生在基于静态设计思想的程序中。

IMO, you're most likely to find ThreadLocal in code that originally was single-threaded until somebody "upgraded" it to use multiple threads. IMO,你最有可能在最初是单线程的代码中找到ThreadLocal ,直到有人“升级”它以使用多个线程。 Thread local comes in handy when a large body of code originally referred to some static variable, and now you need each thread that's running through the same body of code to have its own copy. 当一大堆代码最初引用一些静态变量时,线程本地派上用场,现在你需要每个运行在同一代码体中的线程都有自己的副本。

IMO, ThreadLocal is a code smell---a sign of Bad Design. IMO, ThreadLocal是一种代码气味---一种不良设计的标志。 A well designed, multi-threaded program should not need it. 一个设计良好的多线程程序不应该需要它。

A ThreadLocal doesn't need to be static . ThreadLocal不需要是static Just like any other variable, it depends on your intention: 就像任何其他变量一样,这取决于您的意图:

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
}

The quote you gave refers exactly to the third case listed above. 您提供的报价完全是指上面列出的第三种情况。

ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread ThreadLocal实例通常是希望将状态与线程相关联的类中的私有静态字段

However, it might be perfectly reasonable in some situations to associate state with a thread per instance , in which case you would want to use a non-static ThreadLocal instead (fourth case). 但是,在某些情况下,将状态与每个实例线程相关联可能是完全合理的,在这种情况下,您可能希望使用non-static ThreadLocal (第四种情况)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM