Java ThreadLocal: One Variable, Separate Value Per Thread
Java’s ThreadLocal<T> lets multiple threads share one variable declaration while each thread keeps its own private value for it — no synchronization needed to keep threads from stepping on each other’s value.
The code
Two threads incrementing the same ThreadLocal<Integer> counter field, actually compiled and run, to see what “private per thread” looks like in practice.
public class ThreadLocalDemo {
static ThreadLocal<Integer> counter = ThreadLocal.withInitial(() -> 0);
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
for (int i = 0; i < 3; i++) {
counter.set(counter.get() + 1);
}
System.out.println(Thread.currentThread().getName() + ": " + counter.get());
};
Thread t1 = new Thread(task, "thread-A");
Thread t2 = new Thread(task, "thread-B");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("main: " + counter.get());
}
}
Two threads (thread-A, thread-B) each increment the same counter field 3 times and print their own value. The main thread never touches the counter, then reads it too.
Running it
Real output from the run below:
thread-B: 3
thread-A: 3
main: 0
Each thread landed on 3 — its own private counter, incremented independently of the other thread. main stayed at the withInitial default, 0, since it never called .set().
Takeaway
Same counter declaration, three separate values: thread-A’s 3, thread-B’s 3, main’s 0. That’s what ThreadLocal buys — per-thread state on a shared field, without passing anything explicitly or locking.