Background
Java concurrency and multi-threading is a wide topic. If you are coding for a multi threaded application you need to take care of thread safety. Not all objects are thread safe. Any by thread safety I mean that if a thread is working on some variable and context switch happens and some other thread alters the value of the variable, when 1st thread comes back it will see different value which ultimately will led to inconsistent state (race condition).
One way to ensure thread safety is by Synchronization. In this basically you need to acquire lock before entering a critical region. Other threads have to wait until current that that holds the lock releases it.
Another way to ensure thread safety is by using ThreadLocal variable. This basically ensures each thread has it's own local copy of this variable and cannot access copy held by other threads. Hence the case of race or inconsistency will never arise. Lets see this in more details.
Example
Consider following example -
public class ThreadLocalDemo { public static void main(String args[]) throws InterruptedException { MYRunnable myRunnable = new MYRunnable(); Thread t1 = new Thread(myRunnable); Thread t2 = new Thread(myRunnable); t1.start(); t2.start(); t1.join(); t2.join(); } } class MYRunnable implements Runnable { ThreadLocal<String> myThreadLocal = new ThreadLocal<String>(){ protected String initialValue() { return "InitialValue"; }; }; @Override public void run() { System.out.println(Thread.currentThread().getName() + " : Before : " + myThreadLocal.get()); myThreadLocal.set("NewValue1"); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " : After 1 : " + myThreadLocal.get()); myThreadLocal.set("NewValue2"); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " : After 2 : " + myThreadLocal.get()); myThreadLocal.set("NewValue3"); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " : After 3 : " + myThreadLocal.get()); } }
Output is -
Thread-1 : Before : InitialValue
Thread-0 : Before : InitialValue
Thread-0 : After 1 : NewValue1
Thread-1 : After 1 : NewValue1
Thread-0 : After 2 : NewValue2
Thread-1 : After 2 : NewValue2
Thread-0 : After 3 : NewValue3
Thread-1 : After 3 : NewValue3
Thread-0 : Before : InitialValue
Thread-0 : After 1 : NewValue1
Thread-1 : After 1 : NewValue1
Thread-0 : After 2 : NewValue2
Thread-1 : After 2 : NewValue2
Thread-0 : After 3 : NewValue3
Thread-1 : After 3 : NewValue3
More Info
- Good example of ThreadLocal is SimpleDateFormat. Since SimpleDateFormat is not thread safe, having a global formatter may not work (different threads may alter it's value and may led to inconsistent state) but having per Thread formatter will certainly work.
- What I have generally seen is ThreadLocal variable being declared static and its value being set and retrieved per thread.
- ThreadLocal variable are more like local variable (which are only accessible in the block they are declared). ThreadLocal can only be accessed in same thread.
NOTE
- You need to be very careful about cleaning up any ThreadLocals you get() or set() by using the ThreadLocal's remove() method.
- If you do not clean up when you're done, any references it holds to classes loaded as part of a deployed webapp will remain in the permanent heap and will never get garbage collected. Redeploying/undeploying the webapp will not clean up each Thread's reference to your webapp's class(es) since the Thread is not something owned by your webapp. Each successive deployment will create a new instance of the class which will never be garbage collected.
- So if you use ThreadLocal to store some object instance there is a high risk to have the object stored in the thread local never garbaged when your app runs inside an app server like WebLogic Server, which manage a pool of working thread - even when the class that created this ThreadLocal instance is garbage collected.
No comments:
Post a Comment