自定义实现可跨线程(线程池)的ThreadLocal
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> {
//方法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);
//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; } } }
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 防止内存泄漏 } }
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()); })); } ); } } }