自定义实现可跨线程(线程池)的ThreadLocal

发布时间 2023-08-15 09:22:52作者: 甜菜波波
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());
                        }));
                    }
            );
        }
    }
}