6

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.

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

Please give a better understanding to me. Thanks

Community
  • 1
  • 1
optional
  • 3,260
  • 5
  • 26
  • 47
  • 3
    The answers to the question you linked to do a good job of explaining it. What don't you understand? Do you understand that if you have 10 objects with each a ThreadLocal instance field, then you have 10 different places where some state can be associated with the current thread? You typically don't want that. What you typically want is something like "THE user that is currently using this thread is John", or "THE transaction associated with the current thread is that one". – JB Nizet Mar 03 '16 at 06:50
  • It doesn't have to be technically, but can you name one thing where you didn't want it to be static? – Voo Mar 03 '16 at 06:51
  • @Voo :The thing is that I am just seeing SpringSecurity ContextHolder class where Authentication object is saved in ThreadLocal variable.So to understand that I need to understand ThreadLocal state – optional Mar 03 '16 at 06:53
  • @JBNizet : why I will be needing 10 different object when each copy of thread local is private to each thread – optional Mar 03 '16 at 06:56
  • 1
    Whenever I come across "why would I need this?" questions (as in, whenever I think of one), I've found that the best approach is to just tuck the knowledge away in the back of my mind and not think about it too much. Then, when the topic comes up in the course of real work, I can apply the idea to that concrete example. I look at the "best practices" answer, then come up with alternatives -- and frequently, I end up realizing why the best practice is also the best in _that_ specific case. Repeat that a couple times, and there you go, you've found out why it's a good idea. – yshavit Mar 03 '16 at 07:00
  • @Mukeshkumarsaini yes, indeed, why would you need 10 different objects each having its own ThreadLocal. That's my point. Usually, you want a single "current thread user" or "current thread security context" for the whole application. So it's natural to make it static. – JB Nizet Mar 03 '16 at 07:03
  • @JBNizet will you please provide me a sample example of that in term of plain multi threading not specific to Spring security ? – optional Mar 03 '16 at 07:06
  • @Mukesh I really don't understand your question. Just write a useful, practical example using ThreadLocal. If you can you have obviously proven that there are use cases for non-static fields. If not you've shown to yourself that clearly there's no use *for you* to have such a thing. – Voo Mar 03 '16 at 07:55

4 Answers4

9

Answer to this question lies into ThreadLocal implementation .

Think ThreadLocal as a container

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).

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 .

More detail here

  1. http://www.0xcafefeed.com/2004/06/of-non-static-threadlocals-and-memory/
  2. https://www.appneta.com/blog/introduction-to-javas-threadlocal-storage/
optional
  • 3,260
  • 5
  • 26
  • 47
2

With your implementation you have (logically) 4 different instances of threadID:

  1. r1.threadID{t1} - Instance saved in resource r1 and observed by thread t1. It will be printed by thread t1 if it will be interrupted.

  2. r2.threadID{t2} - Instance saved in resource r2 and observed by thread t2. It will be printed by thread t2 if it will be interrupted.

  3. r1.threadID{t2} - Instance saved in resource r1 and observed by thread t2 in case, e.g., if it calls (directly) r1.run().

  4. r2.threadID{t2} - Instance saved in resource r2 and observed by thread t1 in case, e.g., if it calls (directly) r2.run().

It is unlikely that you need 3-rd and 4-th instances, so you may:

  • 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.

  • Make variable non-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).

Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
  • http://www.javaworld.com/article/2073352/core-java/simply-singleton.html ,is this what you are trying to explain me? – optional Mar 03 '16 at 08:23
  • No, I just tried to explain *what you have* by declaring ThreadLocal variable as *non-static*. In any situation described in my answer you have more than one instance of `threadID`, so it is not a singleton pattern. – Tsyvarev Mar 03 '16 at 19:36
  • In your answer what is r2 ? – optional Mar 04 '16 at 05:17
  • @Mukeshkumarsaini: Oops, I have incorrectly read code in your question as threads used *different* resources. I will rewrite answer (or, may be, will delete it as incorrect). – Tsyvarev Mar 04 '16 at 07:03
  • So, your code is *correct*. But what is a reason to have two **identical** threads, created from *same runnable*? By "identical" I mean that threads cannot be distinguished *outside*, by other threads(execution contexts). `ThreadLocal` variables allow only to disnguish threads from context of the threads themselves. – Tsyvarev Mar 04 '16 at 07:11
0

There is no inherent reason why a ThreadLocal variable needs to be static. 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.

IMO, you're most likely to find ThreadLocal in code that originally was single-threaded until somebody "upgraded" it to use multiple threads. 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. A well designed, multi-threaded program should not need it.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57
0

A ThreadLocal doesn't need to be 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

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).

bcorso
  • 45,608
  • 10
  • 63
  • 75