Welcome!

Recurring Revenue Authors: Elizabeth White, Pat Romanski, Liz McMillan, Yeshim Deniz, Xenia von Wedel

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
Rodrigo Coutinho is part of OutSystems' founders' team and currently the Head of Product Design. He provides a cross-functional role where he supports Product Management in defining the positioning and direction of the Agile Platform, while at the same time promoting model-based development and new techniques to deliver applications in the cloud.
Andrew Keys is Co-Founder of ConsenSys Enterprise. He comes to ConsenSys Enterprise with capital markets, technology and entrepreneurial experience. Previously, he worked for UBS investment bank in equities analysis. Later, he was responsible for the creation and distribution of life settlement products to hedge funds and investment banks. After, he co-founded a revenue cycle management company where he learned about Bitcoin and eventually Ethereal. Andrew's role at ConsenSys Enterprise is a mul...
In his session at 21st Cloud Expo, Raju Shreewastava, founder of Big Data Trunk, provided a fun and simple way to introduce Machine Leaning to anyone and everyone. He solved a machine learning problem and demonstrated an easy way to be able to do machine learning without even coding. Raju Shreewastava is the founder of Big Data Trunk (www.BigDataTrunk.com), a Big Data Training and consulting firm with offices in the United States. He previously led the data warehouse/business intelligence and Bi...
Cell networks have the advantage of long-range communications, reaching an estimated 90% of the world. But cell networks such as 2G, 3G and LTE consume lots of power and were designed for connecting people. They are not optimized for low- or battery-powered devices or for IoT applications with infrequently transmitted data. Cell IoT modules that support narrow-band IoT and 4G cell networks will enable cell connectivity, device management, and app enablement for low-power wide-area network IoT. B...
The Internet of Things will challenge the status quo of how IT and development organizations operate. Or will it? Certainly the fog layer of IoT requires special insights about data ontology, security and transactional integrity. But the developmental challenges are the same: People, Process and Platform and how we integrate our thinking to solve complicated problems. In his session at 19th Cloud Expo, Craig Sproule, CEO of Metavine, demonstrated how to move beyond today's coding paradigm and sh...
What are the new priorities for the connected business? First: businesses need to think differently about the types of connections they will need to make – these span well beyond the traditional app to app into more modern forms of integration including SaaS integrations, mobile integrations, APIs, device integration and Big Data integration. It’s important these are unified together vs. doing them all piecemeal. Second, these types of connections need to be simple to design, adapt and configure...
Cloud computing delivers on-demand resources that provide businesses with flexibility and cost-savings. The challenge in moving workloads to the cloud has been the cost and complexity of ensuring the initial and ongoing security and regulatory (PCI, HIPAA, FFIEC) compliance across private and public clouds. Manual security compliance is slow, prone to human error, and represents over 50% of the cost of managing cloud applications. Determining how to automate cloud security compliance is critical...
Contextual Analytics of various threat data provides a deeper understanding of a given threat and enables identification of unknown threat vectors. In his session at @ThingsExpo, David Dufour, Head of Security Architecture, IoT, Webroot, Inc., discussed how through the use of Big Data analytics and deep data correlation across different threat types, it is possible to gain a better understanding of where, how and to what level of danger a malicious actor poses to an organization, and to determin...
Nicolas Fierro is CEO of MIMIR Blockchain Solutions. He is a programmer, technologist, and operations dev who has worked with Ethereum and blockchain since 2014. His knowledge in blockchain dates to when he performed dev ops services to the Ethereum Foundation as one the privileged few developers to work with the original core team in Switzerland.
Digital Transformation and Disruption, Amazon Style - What You Can Learn. Chris Kocher is a co-founder of Grey Heron, a management and strategic marketing consulting firm. He has 25+ years in both strategic and hands-on operating experience helping executives and investors build revenues and shareholder value. He has consulted with over 130 companies on innovating with new business models, product strategies and monetization. Chris has held management positions at HP and Symantec in addition to ...