ThreadLocal
、InheritableThreadLocal
和 TransmittableThreadLocal
是 Java 中用于线程局部变量的不同实现,适用于不同的场景。
1. ThreadLocal
ThreadLocal
提供了每个线程自己的变量副本。每个线程可以独立修改其副本,而不会影响其他线程的副本。这对于需要线程隔离的数据(例如用户会话信息)非常有用。
使用场景
- 每个线程都有独立的数据副本,并且数据在整个线程生命周期内都不会相互干扰。
- 比如数据库连接、用户会话信息、事务管理等。
示例代码
java
public class ThreadLocalExample {
private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 1);
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
threadLocal.set(2);
System.out.println(Thread.currentThread().getName() + " " + threadLocal.get());
});
Thread thread2 = new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " " + threadLocal.get());
});
thread1.start();
thread2.start();
}
}
2. InheritableThreadLocal
InheritableThreadLocal
是 ThreadLocal
的子类,允许子线程从父线程继承值。这对于需要将上下文信息从父线程传递给子线程的情况非常有用。
使用场景
- 当一个新线程被创建时,需要从父线程继承某些上下文数据。
- 比如,父线程中的安全上下文、用户信息需要传递给子线程。
示例代码
java
public class InheritableThreadLocalExample {
private static InheritableThreadLocal<Integer> inheritableThreadLocal = new InheritableThreadLocal<>();
public static void main(String[] args) {
inheritableThreadLocal.set(3);
Thread thread1 = new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " " + inheritableThreadLocal.get());
});
inheritableThreadLocal.set(5);
Thread thread2 = new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " " + inheritableThreadLocal.get());
});
thread1.start();
thread2.start();
}
}
3. TransmittableThreadLocal
TransmittableThreadLocal
是 ThreadLocal
和 InheritableThreadLocal
的增强版,主要解决了使用线程池等并发框架时,父线程中的上下文信息无法传递到子线程的问题。由阿里巴巴的开源库 TransmittableThreadLocal (TTL) 提供。
使用场景
- 需要在线程池等场景中传递父线程的上下文数据,确保线程池复用线程时上下文信息的一致性。
示例代码
java
import com.alibaba.ttl.TransmittableThreadLocal;
import com.alibaba.ttl.TtlRunnable;
public class TransmittableThreadLocalExample {
private static TransmittableThreadLocal<Integer> transmittableThreadLocal = new TransmittableThreadLocal<>();
public static void main(String[] args) {
transmittableThreadLocal.set(6);
Runnable task = TtlRunnable.get(() -> {
System.out.println(Thread.currentThread().getName() + " " + transmittableThreadLocal.get());
});
Thread thread = new Thread(task);
thread.start();
}
}
总结
ThreadLocal
:适用于每个线程需要独立变量副本的场景。InheritableThreadLocal
:适用于子线程需要继承父线程变量的场景。TransmittableThreadLocal
:适用于需要在线程池等并发环境中传递上下文数据的场景。
选择合适的工具取决于具体的使用需求和场景。