Как починить мертвый ThreadLocal в пуле потоков
Как починить мертвый ThreadLocal в пуле потоков Если положить RequestId / userId / traceId в ThreadLocal и передать задачу в ExecutorService в итоге значение пропадёт. InheritableThreadLocal помогает только при явном создании потока, но не при переиспользовании из пула. Alibaba решили это ещё в 2013 году, а библиотека до сих пор активно поддерживается → TransmittableThreadLocal (TTL). 🔹 Подключается: <dependency> <groupId>com.alibaba</groupId> <artifactId>transmittable-thread-local</artifactId> <version>2.14.5</version> </dependency> 🔹 Используется как обычный ThreadLocal, только умнее: TransmittableThreadLocal<String> traceId = new TransmittableThreadLocal<>(); traceId.set("req-123"); ExecutorService pool = TtlExecutors.getTtlExecutorService( Executors.newFixedThreadPool(4) ); pool.submit(() -> { // "req-123" — доступен здесь, в потоке из пула System.out.println(traceId.get()); }); 🔹 Три способа интеграции → Обернуть Runnable/Callable — TtlRunnable.get(task) → Обернуть пул — TtlExecutors.getTtlExecutorService(pool) → Java Agent — вообще без изменений в коде: -javaagent:transmittable-thread-local.jar Агентовый режим особенно полезен, когда нужно прозрачно встроить TTL в легаси-проект или сторонний фреймворк — он патчит JDK-классы пулов на уровне байткода. 0 зависимостей. Работает с виртуальными потоками (Project Loom). Поддерживает кастомный TtlCopier для глубокого копирования значений при передаче в дочерний поток. Актуально везде, где есть distributed tracing, MDC, tenant isolation или любой per-request контекст в многопоточке. ⚠️ README встретит иероглифами, не пугайся, английская версия лежит в README-EN.md. Java Guru | Мы в Телеграм