小工具类输出ThreadLocal中的值

一个输出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);
                        }
                    }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值