例子1:
public class TestThreadLocal {
public static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
public static void main(String[] args) {
threadLocal.set(new Integer(123));
Thread thread = new MyThread();
thread.start();
System.out.println("main = " + threadLocal.get());
}
static class MyThread extends Thread {
@Override
public void run() {
System.out.println("MyThread = " + threadLocal.get());
}
}
}
输出:
main = 123
MyThread = null
例子2:
改用:InheritableThreadLocal()
public class TestThreadLocal2 {
public static ThreadLocal<Integer> threadLocal = new InheritableThreadLocal<>();
public static void main(String[] args) {
threadLocal.set(new Integer(123));
Thread thread = new MyThread();
thread.start();
System.out.println("main = " + threadLocal.get());
}
static class MyThread extends Thread {
@Override
public void run() {
System.out.println("MyThread = " + threadLocal.get());
}
}
}
输出:
main = 123
MyThread = 123
例子3:
public class TestThreadLocal3 {
public static ThreadLocal<Integer> threadLocal = new InheritableThreadLocal<>();
public static void main(String[] args) {
Thread thread2 = new MyThread2();
thread2.start();
Thread thread = new MyThread();
thread.start();
System.out.println("main = " + threadLocal.get());
}
static class MyThread extends Thread {
@Override
public void run() {
System.out.println("MyThread = " + threadLocal.get());
}
}
static class MyThread2 extends Thread {
@Override
public void run() {
threadLocal.set(new Integer(123));
}
}
}
输出:
main = null
MyThread = null
分析:
例子1中:可以知道如果通过public static ThreadLocal threadLocal = new ThreadLocal<>();则父线程的threadLocal变量不能被子线程说获取。
例子2中:通过InheritableThreadLocal()可以实现子线程获取父线程的变量值。(该方法可以用在异步操作时,异步线程获取主线程的logId,这样就能将logId贯穿全文,但是项目中用到的是线程池,因此,改意义不是很大)
例子3中:通过InheritableThreadLocal()两个子线程间没有关系,则及时用了InheritableThreadLocal()也不能获取对方的变量。
这里给出一个本地线程工具类ThreadLocalUtil:
/**
* 本地线程工具类
*/
@Slf4j
public abstract class ThreadLocalUtil {
private static final ThreadLocal<Map<Object, Object>> RESOURCES = new ThreadLocal<>();
public static Map<Object, Object> getResources() {
return RESOURCES != null ? new HashMap<Object, Object>(RESOURCES.get()) : null;
}
public static void setResources(Map<Object, Object> newResources) {
if (CollectionUtils.isEmpty(newResources)) {
return;
}
RESOURCES.get().clear();
RESOURCES.get().putAll(newResources);
}
private static Object getValue(Object key) {
return RESOURCES.get().get(key);
}
public static Object get(Object key) {
Object value = getValue(key);
log.info("Retrieved value of type [{}] for key [{}] bound to thread [{}].", value.getClass().getName(), key, Thread.currentThread().getName());
return value;
}
public static Object remove(Object key) {
Object value = RESOURCES.get().remove(key);
log.info("Removed value of type [{}] for key [{}] from thread [{}].", value.getClass().getName(), key, Thread.currentThread().getName() );
return value;
}
public static void put(Object key, Object value) {
Preconditions.checkNotNull(key, "key cannot be null");
if (null == value) {
remove(key);
return;
}
RESOURCES.get().put(key, value);
log.info("Bound value of type [{}] for key [{}] to thread [{}].", value.getClass().getName(), key, Thread.currentThread().getName() );
}
public static void remove() {
RESOURCES.remove();
}
}