Course Content
Multithreading in Java
Multithreading in Java
ThreadLocal
ThreadLocal
enables you to avoid multithreading-related mechanisms like synchronization, as data from ThreadLocal
is accessible only within a single thread.
Imagine a banking application where each client has their own account. If multiple clients are using the application simultaneously, their accounts should remain separate. By using ThreadLocal
, each thread (client) gets its own instance of data (account), ensuring that it does not interfere with other threads.
How to use ThreadLocal
ThreadLocal
provides a get()
method and a set()
method, which are self-explanatory.
get()
- retrieves the value from the ThreadLocal
variable.
set()
- set the value to ThreadLocal
variable.
Let's create a program to compare a simple variable with ThreadLocal
.
Each thread will have its own distinct threadLocalCounter
, while the sharedCounter
value will be changed and shared among all threads. The program's output will demonstrate that threadLocalCounter
values are unique for each thread, whereas sharedCounter
will reflect a common result for all threads, which might vary depending on the order in which the threads execute.
ThreadLocalComparison
CounterTask
public class ThreadLocalComparison { public static void main(String[] args) { CounterTask counterTask = new CounterTask(); // Create threads for demonstrating the behavior Thread thread1 = new Thread(counterTask); Thread thread2 = new Thread(counterTask); Thread thread3 = new Thread(counterTask); // Start the threads thread1.start(); thread2.start(); thread3.start(); } }
And after this program works for us, we get the result:
As you can see, the sharedCounter
variable is incremented across different threads, whereas the threadLocalCounter
variable maintains the same value in each thread, because each thread has its own threadLocalCounter
instance that is independent of other threads.
As you might have observed, the code includes a static method ThreadLocal.withInitial()
that sets an initial value for the variable when it is created.
The remove()
method in the ThreadLocal
class is used to remove the value associated with the current thread.
ThreadLocalTask
ThreadLocalRemoveExample
class ThreadLocalTask implements Runnable { // Define a `ThreadLocal` variable with an initial value private static ThreadLocal<String> threadLocalValue = new ThreadLocal<>(); @Override public void run() { // Set a value in the `ThreadLocal` for this thread String threadName = Thread.currentThread().getName(); threadLocalValue.set(threadName + " Value"); // Print the current value System.out.println(threadName + " - ThreadLocal Value before removal: " + threadLocalValue.get()); // Remove the value associated with the current thread threadLocalValue.remove(); // Print the value after removal System.out.println(threadName + " - ThreadLocal Value after removal: " + threadLocalValue.get()); } }
As a result of the program execution:
The program assigns a unique value to ThreadLocal
for each thread and displays this value before and after the remove()
method is invoked. After removing the value with remove()
, ThreadLocal
returns null on subsequent calls to get()
.
Note
Data that are in
ThreadLocal
are not deleted themselves and they must be explicitly deleted!
Why do I Need to Free a Value?
Releasing a value is crucial to prevent memory leaks. ThreadLocal
keeps values linked to threads in a special map that is bound to threads. If a value is not removed, it stays in the map even after the thread's usage is complete, leading to unnecessary objects remaining in memory and ultimately resulting in memory leaks.
Thanks for your feedback!