ThreadLocal传值丢失问题

参考:http://www.spring4all.com/article/948

在Spring Cloud中我们用Hystrix来实现断路器,Zuul中默认是用信号量(Hystrix默认是线程)来进行隔离的,我们可以通过配置使用线程方式隔离。

先来看一下丢失时的代码

public class Main {
    static ThreadLocal<Object> objectThreadLocal = new ThreadLocal<>();
//    static InheritableThreadLocal<Object> objectThreadLocal = new InheritableThreadLocal<>();
    public static void main(String[] args) {
        new Thread(()->{
            objectThreadLocal.set("zj");
            System.out.println("Main:" + Thread.currentThread().getName());
            System.out.println("Main:" + Main.objectThreadLocal.get());
            new Server().run();
        }).start();
    }
    static class Server{
        protected void run(){
            System.out.println("==========================");
            System.out.println("Service:" + Thread.currentThread().getName());
            System.out.println("Service:" + Main.objectThreadLocal.get());
            new Thread(()->{
                new Dao().run();
            }).start();
        }
    }
    static class Dao{
        public void run(){
            System.out.println("==========================");
            System.out.println("Dao:" + Thread.currentThread().getName());
            System.out.println("Dao:" + Main.objectThreadLocal.get());
        }
    }
}

运行代码,结果:

线程变了,也就数据丢失了,

再来看一下不丢失数据的代码

public class Main {
//    static ThreadLocal<Object> objectThreadLocal = new ThreadLocal<>();
    static InheritableThreadLocal<Object> objectThreadLocal = new InheritableThreadLocal<>();
    public static void main(String[] args) {
        new Thread(()->{
            objectThreadLocal.set("zj");
            System.out.println("Main:" + Thread.currentThread().getName());
            System.out.println("Main:" + Main.objectThreadLocal.get());
            new Server().run();
        }).start();
    }
    static class Server{
        protected void run(){
            System.out.println("==========================");
            System.out.println("Service:" + Thread.currentThread().getName());
            System.out.println("Service:" + Main.objectThreadLocal.get());
            new Thread(()->{
                new Dao().run();
            }).start();
        }
    }
    static class Dao{
        public void run(){
            System.out.println("==========================");
            System.out.println("Dao:" + Thread.currentThread().getName());
            System.out.println("Dao:" + Main.objectThreadLocal.get());
        }
    }
}

上述代码也就是吧ThreadLocal替换为InheritableThreadLocal,这里不解释InheritableThreadLocal,比较简单。感兴趣的可以自己瞅瞅源码就知道啦。

再来看一下运行后的结果:

即使是线程改变 了,值也是可以取到的,至此我也就做了个简单的测试。

 

 

版本测试二

package book.test;

/**
 * 父线程的ThreadLocal里面的值子线程获取不到演示,如果换成InheritableThreadLocal
 * 就成功子线程也能获取父线程传过来的ThreadLocal的值
 */
public class ThreadLocalTest {

    public static void main(String[] args) {
        new ParamentThread().start();
    }


    public static class ParamentThread extends Thread{
        InheritableThreadLocal<String> paramentThreadLocal=new InheritableThreadLocal();
        @Override
        public void run() {
            paramentThreadLocal.set("paramentThreadLocal");
//            super.run();
            System.out.println("I am is ParamentThread:  "+paramentThreadLocal.get());
            ChindThread chindThread=new ChindThread(paramentThreadLocal);
            new Thread(chindThread).start();
        }
    }

    public static class ChindThread implements Runnable{
        InheritableThreadLocal<String> chindThreadLocal=null;
        public ChindThread(InheritableThreadLocal<String> paramentThreadLocal){
            this.chindThreadLocal=paramentThreadLocal;
        }
        @Override
        public void run() {
           if(chindThreadLocal==null){
               System.out.println("chindThreadLocal==null");
           }else{
               System.out.println("chindThreadLocal!=null:  "+chindThreadLocal.get());
           }
        }
    }
}

 

 

 

 

 

 

http://www.spring4all.com/article/948文章写得比较好,感兴趣的可以自己去看看。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章