一个输出ThreadLocal中的值小工具类,代码如下:
package com.zkn.utils; import org.springframework.core.NamedThreadLocal; import java.lang.ref.Reference; import java.lang.reflect.Field; import java.util.*; /** * Created by zkn on 2017/10/4. */ public class ThreadLocalUtil { public static void dumpThreadDetails() { try { //获取当前线程对象 Thread thread = Thread.currentThread(); //获取Thread中的threadLocals对象 Field threadLocals = Thread.class.getDeclaredField("threadLocals"); threadLocals.setAccessible(true); //ThreadLocalMap是ThreadLocal中的一个内部类,并且访问权限是default // 这里获取的是ThreadLocal.ThreadLocalMap Object threadLocalMap = threadLocals.get(thread); //这里要这样获取ThreadLocal.ThreadLocalMap Class threadLocalMapClazz = Class.forName("java.lang.ThreadLocal$ThreadLocalMap"); //获取ThreadLocalMap中的Entry对象 Field tableField = threadLocalMapClazz.getDeclaredField("table"); tableField.setAccessible(true); //获取ThreadLocalMap中的Entry Object[] objects = (Object[]) tableField.get(threadLocalMap); //获取ThreadLocalMap中的Entry Class entryClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap$Entry"); //获取ThreadLocalMap中的Entry中的value字段 Field entryValueField = entryClass.getDeclaredField("value"); entryValueField.setAccessible(true); //Entry继承了WeakReference,WeakReference继承了Reference Field referEnceField = Reference.class.getDeclaredField("referent"); referEnceField.setAccessible(true); Arrays.stream(objects).filter(obj -> obj != null).forEach((obj) -> { try { Object value = entryValueField.get(obj); if (value != null) { if (value instanceof Reference) { Reference ref = (Reference) value; System.out.println(" ref " + ref.getClass().getName() + " ref to " + ref.get()); } else { System.out.println(value); } } } catch (IllegalAccessException e) { e.printStackTrace(); } }); } catch (Exception e) { e.printStackTrace(); } } }我们来测试一下:
public static void main(String[] args) { ThreadLocal<Map<String, String>> threadLocal = new ThreadLocal(); Map<String, String> maps = new HashMap<String, String>() {{ put("zhangsan", "lisiwww"); put("zhangsan000000", "lisi7845www"); put("zha0124545ngsan", "lisiw02255ww"); }}; threadLocal.set(maps); ThreadLocal<List<String>> threadLocalList = new ThreadLocal(); List<String> lists = new ArrayList<String>() {{ add("qwwweweqqqqqq2222"); add("qww111weweqqqqqq2222"); add("qwww44444eweqqqqqq2222"); }}; threadLocalList.set(lists); dumpThreadDetails(); }
在Spring中有一个ThreadLocal的扩展类:NamedThreadLocal,Spring中的很多资源都是保存在这里面,如果我们要输出NamedThreadLocal中的值的话,只需要这样改动一下就行了:
if (value != null) { ThreadLocal threadLocal = (ThreadLocal) referEnceField.get(obj); if (threadLocal instanceof NamedThreadLocal) { System.out.print("spring threadlocal name: " + threadLocal + " value: "); } if (value instanceof Reference) { Reference ref = (Reference) value; System.out.println(" ref " + ref.getClass().getName() + " ref to " + ref.get()); } else { System.out.println(value); } }