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文章寫得比較好,感興趣的可以自己去看看。

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