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.