package com.ankurm.vt; // Explained in docs/01-inheritable-threadlocal.md -- run via scripts/run-all.sh, output captured in docs/output/ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** Confirms, with no Spring involved, how InheritableThreadLocal behaves for * (a) a fresh platform Thread, (b) a reused thread from a fixed pool, and * (c) a fresh virtual thread. */ public class Demo1PlainThreadLocal { static final InheritableThreadLocal CTX = new InheritableThreadLocal<>(); public static void main(String[] args) throws Exception { System.out.println("=== Demo 1: InheritableThreadLocal across thread models ==="); // (a) fresh platform Thread inherits at construction time CTX.set("request-A"); Thread t = new Thread(() -> System.out.println("fresh platform thread sees: " + CTX.get())); t.start(); t.join(); // (b) reused thread from a fixed pool: the SECOND task on the same worker // still carries whatever was set when the pool thread was originally created ExecutorService pool = Executors.newFixedThreadPool(1); CTX.set("request-B"); pool.submit(() -> System.out.println("pool thread, task 1, sees: " + CTX.get())).get(); CTX.set("request-C"); // caller's context changed pool.submit(() -> System.out.println("pool thread, task 2 (reused), sees: " + CTX.get() + " <-- stale, not request-C")).get(); pool.shutdown(); // (c) fresh virtual thread, never reused CTX.set("request-D"); Thread vt = Thread.ofVirtual().start(() -> System.out.println("fresh virtual thread sees: " + CTX.get())); vt.join(); CTX.remove(); } }