天天看點

個人版ThreadLocal

ThreadLocal簡介

請借鑒的一篇文章

個人了解

ThreadLocal 用的比較多的就是用來維護一個對象。讓他在多線程通路下處于線程安全。來保證資料通路的正确性。多線程下不去共享同一個變量。一個線程隻維護一個執行個體。線程若被銷毀随着該線程所持有的對象也會被銷毀。(銷毀可以了解成回收)
個人版ThreadLocal

看一手我寫dome

@Slf4j
public class MyThreadLocal {
    public static void main(String[] args) {
        //多線程通路時,資料間隔離。一個線程隻持有一個對象
        ThreadLocal<Cat> threadLocal = new ThreadLocal<>();

        for (int i = 1, size = 10; i <= size; i++) {
            Cat cat = new Cat();
            int finalI = i;
            new Thread(() -> {
                cat.setId(finalI);
                cat.setAge(finalI);
                cat.setName("我家的土貓:" + finalI);
                cat.setSex("男");
                threadLocal.set(cat);

                log.info("main: " + threadLocal.get());
                threadLocal.remove();

                log.info("main: " + threadLocal.get());
            }, "sxy"+i).start();
        }
    }
}
//10個線程,擁有10個對象
           
Cat cat = new Cat(); 這個對象一定要放在這個for循環裡不然 控制台列印的資料不是我們想要的。

為什麼?

一個線程持有一個執行個體副本。new對象的這個操作,如果放在for外的話,就是一個執行個體。

底層分析

//擷取ThreadLocal中的對象
public T get() {
        Thread t = Thread.currentThread();//傳回對目前正在執行的線程對象的引用
        ThreadLocalMap map = getMap(t); //目前:擷取ThreadLocalMap 
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);//這個map裡是否有目前線程
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        //沒有就是set
        return setInitialValue();
    }
 //往:ThreadLocal 對象中擷取對象
 public void set(T value) {
        Thread t = Thread.currentThread();//傳回對目前正在執行的線程對象的引用
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
//ThreadLocal 删除目前線程中的記憶體執行個體
public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }
           

ThreadLocalMap底層

//key目前線程 value 目前的引用對象
private ThreadLocalMap(ThreadLocalMap parentMap) {
            Entry[] parentTable = parentMap.table;
            int len = parentTable.length;
            setThreshold(len);
            table = new Entry[len];

            for (int j = 0; j < len; j++) {
                Entry e = parentTable[j];
                if (e != null) {
                    @SuppressWarnings("unchecked")
                    ThreadLocal<Object> key = (ThreadLocal<Object>) e.get();
                    if (key != null) {
                        Object value = key.childValue(e.value);
                        Entry c = new Entry(key, value);
                        int h = key.threadLocalHashCode & (len - 1);
                        while (table[h] != null)
                            h = nextIndex(h, len);
                        table[h] = c;
                        size++;
                    }
                }
            }
        }
        
           

2021年8月22号:

強軟弱虛

強引用如果對象,有引用指向 就不會被回收

軟引用 :記憶體不足時,進行回收。

弱引用:直接回收

個人版ThreadLocal