InheritableThreadLocal源碼閱讀

在進行多線程編程時,咱們常常須要線程池子線程和父線程進行ThreadLocal信息傳遞,實現一些業務處理。編程

先看一個例子

public class App {
    static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();

    public static void main(String[] args) {
        threadLocal.set(new Integer(123));

        Thread thread = new SonThread();
        thread.start();

        System.out.println("main = " + threadLocal.get());
    }

    static class SonThread extends Thread {
        @Override
        public void run() {
            System.out.println("SonThread = " + threadLocal.get());
        }
    }
}

輸出結果

main = 123
SonThread = null

使用InheritableThreadLocal

static ThreadLocal<Integer> threadLocal = new InheritableThreadLocal<Integer>();

輸出結果

main = 123
SonThread = 123

經過InheritableThreadLocal咱們能夠實現父子線程之間ThreadLocal信息傳遞。多線程

查看InheritableThreadLocal源碼

重寫了getMap和createMap方法。ide

public class InheritableThreadLocal<T> extends ThreadLocal<T> {

    ThreadLocalMap getMap(Thread t) {
       return t.inheritableThreadLocals;
    }

    void createMap(Thread t, T firstValue) {
        t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
    }
  • 屬性inheritableThreadLocals爲ThreadLocal屬性,說明ThreadLocal爲父線程和子線程實現了不一樣的ThreadLocalMap存儲。
  • 當咱們建立一個新的線程的時候X,X線程就會有 ThreadLocalMap 類型的 inheritableThreadLocals ,由於它是 Thread 類的一個屬性。
/* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;

    /*
     * InheritableThreadLocal values pertaining to this thread. This map is
     * maintained by the InheritableThreadLocal class.
     */
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
  • 再經過一個 for 循環,不斷的把當前線程的這些值複製到咱們新建立的線程X 的inheritableThreadLocals 中。就這樣,就ok了。
  • 結果就是咱們建立的新線程X 的inheritableThreadLocals 變量中已經有了值了。
  • 那麼我在新的線程X中調用threadlocal.get() 方法,首先會獲得新線程X 的 inheritableThreadLocals,而後,再根據threadlocal.get()中的 threadlocal,就可以獲得這個值。
  • 這樣就避免了 新線程中獲得的 threadlocals 沒有東西。以前就是由於沒有東西,因此纔拿不到值。

因此說 整個 InheritableThreadLocal 的實現原理就是這樣的。this

使用例子

public static void main(String[] args) {
        threadLocal.set(new Integer(123));

        ExecutorService fixPool = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            final int index = i;
            try {
                Thread.sleep(index * 500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            fixPool.execute(new Runnable() {
                public void run() {
                    System.out.println("Thread = " + Thread.currentThread().getName() + ", SonThread = " + threadLocal.get());
                }
            });
        }
        fixPool.shutdown();
    }

使用前:線程

Thread = pool-1-thread-1, SonThread = null
Thread = pool-1-thread-2, SonThread = null
Thread = pool-1-thread-3, SonThread = null
Thread = pool-1-thread-4, SonThread = null
Thread = pool-1-thread-5, SonThread = null
Thread = pool-1-thread-6, SonThread = null
Thread = pool-1-thread-7, SonThread = null
Thread = pool-1-thread-8, SonThread = null
Thread = pool-1-thread-9, SonThread = null
Thread = pool-1-thread-10, SonThread = null

使用InheritableThreadLocal以後:code

Thread = pool-1-thread-1, SonThread = 123
Thread = pool-1-thread-2, SonThread = 123
Thread = pool-1-thread-3, SonThread = 123
Thread = pool-1-thread-4, SonThread = 123
Thread = pool-1-thread-5, SonThread = 123
Thread = pool-1-thread-6, SonThread = 123
Thread = pool-1-thread-7, SonThread = 123
Thread = pool-1-thread-8, SonThread = 123
Thread = pool-1-thread-9, SonThread = 123
Thread = pool-1-thread-10, SonThread = 123
相關文章
相關標籤/搜索