Welcome!

Open Source Cloud Authors: Liz McMillan, Pat Romanski, Yeshim Deniz, Elizabeth White, Zakia Bouachraoui

Related Topics: Java IoT, Industrial IoT, Microservices Expo, Open Source Cloud, Machine Learning , Recurring Revenue

Java IoT: Blog Post

A Painless Introduction to Java’s ThreadLocal Storage

Best practices for using another powerful class: ThreadLocal from java.lang

In my last blog, we explored WeakHashMap which is based by WeakReference in Java. Now let's look at some best practices for using another powerful class: ThreadLocal from java.lang, which is also implemented using WeakReference.

What is ThreadLocal? A simple example
As its name suggests, a single instance of ThreadLocal can store different values for each thread independently. Therefore, the value stored in a ThreadLocal instance is specific (local) to the current running Thread, any other code logic running on the same thread will see the same value, but not the values set on the same instance by other threads. (There are exceptions, like InhertiableThreadLocal, which inherits parent thread's values by default.)

Let's consider this example:

We have a TransactionManager class that provide static methods to:

  • Start a transaction with a generated ID
  • Store that ID as a static field and provide a transaction ID getter method to other code logic that needs to know the current transaction ID.

In a single threaded environment, TransactionManager can simply store the ID as a static field and return as is. However, this will certainly not work in a multiple-threaded environment. Imagine multiple threads are using TransactionManager - transaction IDs generated by each thread can overwrite each other as there is only one static instance of transaction ID. One may synchronize and block other transactions to avoid overwrites, but this would totally defeat the purpose of having multiple threads.

In order to solve this problem, ThreadLocal provides a very neat solution:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class TransactionManager { private static final ThreadLocal<String> context = new ThreadLocal<String>(); public static void startTransaction() { //logic to start a transaction //... context.set(generatedId); } public static String getTransactionId() { return context.get(); } public static void endTransaction() { //logic to end a transaction //... context.remove(); } }

Different thread that starts transactions via TransactionManager will get its own transaction ID stored in the context. Any logic within the same thread can call getTransactionId() later on to retrieve the value belongs/local to that Thread. So problem's solved!

The Internals of ThreadLocal and How it Works

Let's drill down a little bit into the ThreadLocal's internals. ThreadLocal is implemented by having a Map (a ThreadLocalMap) as field (with WeakReference entry) within each Thread instance. (There are actually 2 maps; the second one is used for InheritabeleThreadLocal, but let's not complicate the picture). The keys of those maps are the corresponding ThreadLocals themselves. Therefore, when a set/get is called on a ThreadLocal, it looks at the current thread, find the map, and look up the value with "this" ThreadLocal instance.

Still confused? I certainly am. Let's look at a real example.

  • Code running in Thread 1 calls set() on ThreadLocal instance "A" with value "123″
  • Code running in Thread 2 calls set() on ThreadLocal instance "A" with value "234″
  • Code running in Thread 1 calls set() on ThreadLocal instance "B" with value "345″

And this is the end result:

Thread 1 (the instance)'s field ThreadLocalMap (m1) has 2 entries:

KeyValue
ThreadLocal A "123″
ThreadLocal B "345″

Thread 2 (the instance)'s field ThreadLocalMap (m2) has 1 entry:

KeyValue
ThreadLocal A "234″

Now if some code logic in Thread 1 calls get() on ThreadLocal instance "A", the ThreadLocal logic will lookup the current Thread, which is instance Thread 1, then access the field ThreadLocalMap of that Thread instance, which is m1, it can then lookup the value by using m1.get(this), with "this" as ThreadLocal and the result is "123″

Now what to watch out for!
Did I hear weak reference for ThreadLocal entries? Does that mean I don't have to clean up? Well, it's not quite that simple.

First of all, the value object put into the ThreadLocal would not purge itself (garbage collected) if there are no more Strong references to it. Instead, the Weak reference is done on the thread instance, which means Java garbage collection would clean up the ThreadLocal map if the thread itself is not strongly referenced elsewhere.

So now the question is: when would the Thread object get garbage collected?

The answer is: it depends, but always assume the thread is long running. 2 common examples:

  • Servlets. The threads that handle servlet requests usually stay alive in the container for the lifetime of the server instance. Code logic that uses ThreadLocal might be referenced indirectly by servlets.
  • Thread pooling java.util.concurrent.Executors. Java encourages recycling threads!

A typical usage of Executor introduced in Java 1.5, if ThreadLocal maps are not cleaned up properly after a transaction is done, next TransactionProcessingTask might inherit values from another previous unrelated task!

1 2 ExecutorService service = Executors.newFixedThreadPool(10); service.submit(new TransactionProcessingTask());

Be careful with initialization of ThreadLocal, below is an implementation of a counter by Thread. Can you tell what is wrong in the below initialzation?

1 2 3 4 5 6 7 8 9 10 11 12 public class Counter { private static ThreadLocal<Integer> counter = new ThreadLocal<Integer>(); static { counter.set(0); } public int getCountInThread() { return counter.get(); } //.... }

The counter would not get initialized correctly! Though the counter is declared as static, it CANNOT be initialized by having a static initializer, as the initializer only runs once when the first thread references the Counter class. When the second thread comes in, it does not run counter.set(0) on that thread, therefore counter.get() returns null instead of 0! One solution is to sublcass ThreadLocal and override the initialValue() method to assign non-null initial value.

With these in mind, you can probably picture the consequences of not cleaning up after ourselves! An operation that runs on a recycled thread might inherit the values from previous operation on the same thread! Besides, it can also cause memory leaks as the instance stored in ThreadLocal will never get garbage collected if the thread is alive.

As a rule of thumb, always clean up/reset your threadlocal after you have finished your "unit of operation"! Even though the current code might be simple enough to bypass the cleanups, it might be adapted and integrated into servlets/thread pooling later on! After all, cleaning up responsibly is always appreciated both in the realms of programming and real life.

More Stories By Patson Luk

A Java developer who has spent the better part of the last decade working on financial services applications with companies from HSBC to Mobilearth and Parasoft, Patson is experienced in various aspects of computer systems, from large scale enterprise banking system to lightweight mobile payment solutions. He now leads Java instrumentation and tool development for the TraceView product at AppNeta. Patson's focus is on using java bytecode manipulation technologies to gain greater visibility into the full spectrum of Java based technologies. This includes higher level application frameworks from Spring and Struts to Webflow, AppServers from TomCat to JBoss, and Databases from MySQL to Oracle. He's also writes frequently on the AppNeta blog - www.appneta.com/blog

IoT & Smart Cities Stories
René Bostic is the Technical VP of the IBM Cloud Unit in North America. Enjoying her career with IBM during the modern millennial technological era, she is an expert in cloud computing, DevOps and emerging cloud technologies such as Blockchain. Her strengths and core competencies include a proven record of accomplishments in consensus building at all levels to assess, plan, and implement enterprise and cloud computing solutions. René is a member of the Society of Women Engineers (SWE) and a m...
DXWorldEXPO | CloudEXPO are the world's most influential, independent events where Cloud Computing was coined and where technology buyers and vendors meet to experience and discuss the big picture of Digital Transformation and all of the strategies, tactics, and tools they need to realize their goals. Sponsors of DXWorldEXPO | CloudEXPO benefit from unmatched branding, profile building and lead generation opportunities.
Founded in 2000, Chetu Inc. is a global provider of customized software development solutions and IT staff augmentation services for software technology providers. By providing clients with unparalleled niche technology expertise and industry experience, Chetu has become the premiere long-term, back-end software development partner for start-ups, SMBs, and Fortune 500 companies. Chetu is headquartered in Plantation, Florida, with thirteen offices throughout the U.S. and abroad.
SYS-CON Events announced today that DatacenterDynamics has been named “Media Sponsor” of SYS-CON's 18th International Cloud Expo, which will take place on June 7–9, 2016, at the Javits Center in New York City, NY. DatacenterDynamics is a brand of DCD Group, a global B2B media and publishing company that develops products to help senior professionals in the world's most ICT dependent organizations make risk-based infrastructure and capacity decisions.
CloudEXPO New York 2018, colocated with DXWorldEXPO New York 2018 will be held November 11-13, 2018, in New York City and will bring together Cloud Computing, FinTech and Blockchain, Digital Transformation, Big Data, Internet of Things, DevOps, AI, Machine Learning and WebRTC to one location.
DXWordEXPO New York 2018, colocated with CloudEXPO New York 2018 will be held November 11-13, 2018, in New York City and will bring together Cloud Computing, FinTech and Blockchain, Digital Transformation, Big Data, Internet of Things, DevOps, AI, Machine Learning and WebRTC to one location.
@DevOpsSummit at Cloud Expo, taking place November 12-13 in New York City, NY, is co-located with 22nd international CloudEXPO | first international DXWorldEXPO and will feature technical sessions from a rock star conference faculty and the leading industry players in the world. The widespread success of cloud computing is driving the DevOps revolution in enterprise IT. Now as never before, development teams must communicate and collaborate in a dynamic, 24/7/365 environment. There is no time t...
Cloud-enabled transformation has evolved from cost saving measure to business innovation strategy -- one that combines the cloud with cognitive capabilities to drive market disruption. Learn how you can achieve the insight and agility you need to gain a competitive advantage. Industry-acclaimed CTO and cloud expert, Shankar Kalyana presents. Only the most exceptional IBMers are appointed with the rare distinction of IBM Fellow, the highest technical honor in the company. Shankar has also receive...
A valuable conference experience generates new contacts, sales leads, potential strategic partners and potential investors; helps gather competitive intelligence and even provides inspiration for new products and services. Conference Guru works with conference organizers to pass great deals to great conferences, helping you discover new conferences and increase your return on investment.
Headquartered in Plainsboro, NJ, Synametrics Technologies has provided IT professionals and computer systems developers since 1997. Based on the success of their initial product offerings (WinSQL and DeltaCopy), the company continues to create and hone innovative products that help its customers get more from their computer applications, databases and infrastructure. To date, over one million users around the world have chosen Synametrics solutions to help power their accelerated business or per...