自定义实现可跨线程(线程池)的ThreadLocal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | package Test0814; import com.google.common.collect.Maps; import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; public class MyThreadLocal<T> extends InheritableThreadLocal<T> { <br> //方法1 public static final InheritableThreadLocal<MyThreadLocal<Object>> mapThreadLocal= new InheritableThreadLocal<>(); //方法2 public static final Map<Thread,MyThreadLocal<Object>> maps= Maps.newConcurrentMap(); public MyThreadLocal(){ super (); } @Override public void set(T t){ super .set(t);<br> //set的时候降当前对象存储到map或者threadlocal,然后再实力化包装的runnable的时候,需要拿到当前对象和值 赋给RunnableWrapper ,以便带给任务内的代码获取父线程的值 this .addThis(); maps.put(Thread.currentThread(),(MyThreadLocal<Object>) this ); } @Override public T get(){ return super .get(); } private void addThis(){ mapThreadLocal.set((MyThreadLocal<Object>) this ); } public static class TransInner{ public static MyThreadLocal<Object> getCap(){ MyThreadLocal<Object> parentLocalMap=mapThreadLocal.get(); return parentLocalMap; } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | package Test0814; import java.util.Map; import java.util.logging.Logger; // 包装的Runnable,以便将父线程的值传到子线程内 public class RunableWrapper implements Runnable { private Runnable runnable; private Object parentMapValue= null ; private MyThreadLocal myThreadLocal=MyThreadLocal.maps.get(Thread.currentThread()); //获取父线程的ThreadLocal对象,也可以写在构造器内 public static RunableWrapper getRunnable(Runnable runnable){ return new RunableWrapper(runnable); } public RunableWrapper() { } public RunableWrapper(Runnable runnable){ this .runnable=runnable; this .parentMapValue=myThreadLocal.get(); //获取父对象TTL的值 // this.parentMapValue=myThreadLocal.get(); // this.myThreadLocal=myThreadLocal; } @Override public void run() { // System.out.println("p="+parentMapValue); // System.out.println("myThreadLocal="+myThreadLocal); myThreadLocal.set(parentMapValue); //将父线程的值写入子线程,这样在执行run方法的时候就能获取 父线程的值了 runnable.run(); myThreadLocal.remove(); //用完后remove 防止内存泄漏 } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | package Test0814; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @Auther: qint * @Date: 2023/08/14 11:15 * @Description: */ public class Main2 { private static MyThreadLocal threadLocal = new MyThreadLocal(); private static ExecutorService ES = Executors.newFixedThreadPool( 1 ); public static void main(String[] args) { for ( int i = 0 ; i < 10 ; i++) { final int a = i; ES.submit(() -> { Thread.currentThread().setName( "儿子线程" + a); String parentName = Thread.currentThread().getName(); threadLocal.set(parentName); System.out.println( "儿子线程的ThreadLocal:" + threadLocal.get()); ES.submit(RunableWrapper.getRunnable(() -> { Thread.currentThread().setName(parentName + " 的儿子线程" ); System.out.println(parentName + "的儿子线程的ThreadLocal:" + threadLocal.get()); })); } ); } } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
2022-08-15 java过滤器(Filter)、Spring拦截器(Handler)