Анатомия ThreadLocal

интервью Java задняя часть база данных

  1. Что такое ThreadLocal? Каковы преимущества ThreadLocal?
  2. Будет ли ThreadLocal вызывать утечки памяти?
  3. Что делать, если возникает конфликт при сохранении Value?
  4. Почему слабая ссылка на Entry в ThreadLocalMap?

  • Официальное описание: Этот класс предоставляет локальные переменные потока. Эти переменные отличаются от своих обычных аналогов тем, что каждый поток, обращающийся к переменной (через свои методы get или set), имеет свою собственную локальную переменную, которая не зависит от инициализированной копии переменной. Экземпляры ThreadLocal обычно представляют собой закрытые статические поля в классах, которые хотят связать состояние с потоком (например, идентификатор пользователя или идентификатор транзакции).

  • собственное понимание Локальная переменная потока ThreadLocal. Создайте копию переменной для каждого потока. СДЕЛАТЬ

внутренняя структура

  • ThreadLocal состоит из ThreadLocalMap, а ключ — ThreadLocal;
  • По существу: ThreadLocalMap содержит массив Entry;

ключевой метод

1. ThreadLocal#set()

    public void set(T value) {
        Thread t = Thread.currentThread();
        //重要:根据线程获取Map
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

Получить карту в соответствии с текущим потоком, если карта пуста, createMap().

  • Что делает ThreadLocal#getMap()?
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;//返回一个**线程绑定**的ThreadLocalMap
    }
  • Что делает ThreadLocal#createMap()?
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

Видно, что у самого Thread есть встроенный ThreadLocalMap.

Затем следующий момент — посмотреть, как инициализируется ThreadLocalMap.

1.1 Создание процесса ThreadLocalMap (процесс инициализации)

    ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
            //初始化一个长度=16的对象数组。Entry extends WeakReference
            table = new Entry[INITIAL_CAPACITY];
            //确定Hash值
            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
            //设值
            table[i] = new Entry(firstKey, firstValue);
            size = 1;
            setThreshold(INITIAL_CAPACITY);
    }

1.2 Конструктор, создайте Entry и установите значение

(Важно! Так что используйте скриншоты)

image_1cnrgn0mi1ceqoch1gprpkv1i0738.png-100kB

расширять:

  1. Почему слабая ссылка на Entry в ThreadLocalMap?
  2. Но слабо ссылается только Key, когда происходит следующий GC,

1.3 Как установить значение?

Проблемный момент: что делать, если есть конфликт хэшей?

        private void set(ThreadLocal<?> key, Object value) {
            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1);

            for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {
                ThreadLocal<?> k = e.get();
                //
                if (k == key) {
                    e.value = value;
                    return;
                }

                if (k == null) {
                    replaceStaleEntry(key, value, i);
                    return;
                }
            }

            tab[i] = new Entry(key, value);
            int sz = ++size;
            if (!cleanSomeSlots(i, sz) && sz >= threshold)
                rehash();
        }

Решение: Способ, которым ThreadLocalMap разрешает конфликты хэшей, заключается в простом увеличении или уменьшении размера шага на 1, чтобы найти следующее соседнее местоположение.

2. ThreadLocal#get()

    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

Сценарии применения

Подключение к базе данных, управление сессиями

Ссылаться на

  1. ThreadLocal-Углубленный анализ вопросов интервью
  2. [Параллельное программирование на Java] Углубленный анализ ThreadLocal (8)