Java 语言 多线程上下文传递 ThreadLocal与InheritableThreadLocal

Java阿木 发布于 21 天前 3 次阅读


摘要:

在Java多线程编程中,线程上下文传递是一个常见的需求。ThreadLocal和InheritableThreadLocal是Java提供的一种线程局部变量实现,它们允许每个线程拥有自己的独立变量副本,从而避免线程间的变量干扰。本文将深入探讨ThreadLocal和InheritableThreadLocal的使用场景、原理以及代码实现。

一、

在多线程环境中,共享资源的使用需要谨慎处理,以避免竞态条件、死锁等问题。在某些情况下,我们需要为每个线程提供独立的变量副本,以便线程之间互不干扰。ThreadLocal和InheritableThreadLocal正是为了解决这类问题而设计的。

二、ThreadLocal

ThreadLocal是一个线程局部变量工具类,它为每个使用该变量的线程提供一个独立的变量副本。每个线程都可以独立地改变自己的副本,而不会影响到其他线程中的副本。

1. ThreadLocal的使用场景

- 需要为每个线程保存独立数据时,如数据库连接、用户会话信息等。

- 需要避免在多个线程间共享变量时,如线程安全计数器。

2. ThreadLocal的原理

ThreadLocal内部维护了一个ThreadLocalMap,该Map以Thread为键,以ThreadLocal对象为值。每个ThreadLocal对象都有一个ThreadLocalMap的Entry作为其存储位置。

3. ThreadLocal的代码实现

java

public class ThreadLocal<T> {


private ThreadLocalMap threadLocalMap = new ThreadLocalMap(this);

public T get() {


Thread t = Thread.currentThread();


ThreadLocalMap map = threadLocalMap.get(t);


if (map != null) {


ThreadLocalMap.Entry e = map.getEntry(this);


if (e != null) {


@SuppressWarnings("unchecked")


T result = (T) e.value;


return result;


}


}


return setInitialValue();


}

private T setInitialValue() {


T value = initialValue();


Thread t = Thread.currentThread();


ThreadLocalMap map = t.threadLocalMap;


if (map == null) {


map = new ThreadLocalMap(this);


}


map.set(this, new ThreadLocalMap.Entry(this, value));


return value;


}

protected T initialValue() {


return null;


}


}


三、InheritableThreadLocal

InheritableThreadLocal是ThreadLocal的一个子类,它允许父线程的变量值被子线程继承。在创建子线程时,子线程会继承父线程的InheritableThreadLocal变量值。

1. InheritableThreadLocal的使用场景

- 需要为子线程传递父线程的变量值时,如线程池中的线程。

2. InheritableThreadLocal的原理

InheritableThreadLocal在创建子线程时,会复制父线程的ThreadLocalMap,并将复制后的Map赋值给子线程。

3. InheritableThreadLocal的代码实现

java

public class InheritableThreadLocal<T> extends ThreadLocal<T> {


protected T childValue(T parentValue) {


return parentValue;


}

public T get() {


Thread t = Thread.currentThread();


Thread parentThread = t.getParent();


if (parentThread != null) {


ThreadLocalMap parentThreadLocalMap = parentThread.threadLocalMap;


if (parentThreadLocalMap != null) {


ThreadLocalMap.Entry parentEntry = parentThreadLocalMap.getEntry(this);


if (parentEntry != null) {


@SuppressWarnings("unchecked")


T parentValue = (T) parentEntry.value;


return childValue(parentValue);


}


}


}


return super.get();


}

public void set(T value) {


Thread t = Thread.currentThread();


Thread parentThread = t.getParent();


if (parentThread != null) {


ThreadLocalMap parentThreadLocalMap = parentThread.threadLocalMap;


if (parentThreadLocalMap != null) {


parentThreadLocalMap.set(this, new ThreadLocalMap.Entry(this, value));


}


}


super.set(value);


}


}


四、总结

ThreadLocal和InheritableThreadLocal是Java多线程编程中常用的工具类,它们为线程提供了独立的变量副本,避免了线程间的变量干扰。在实际开发中,合理使用ThreadLocal和InheritableThreadLocal可以提高程序的性能和稳定性。

本文详细介绍了ThreadLocal和InheritableThreadLocal的使用场景、原理以及代码实现,希望对读者有所帮助。在实际应用中,应根据具体需求选择合适的工具类,以达到最佳效果。