ThreadLocal quick look

Welcome thumbs up reading, learning exchanges together, have questions, please leave a message.
There are also open source on GitHub JavaHouse welcome star

1 introduction

In Java8 inside, ThreadLocal is a generic class. This class provides thread variable. Each thread has its own variables. what does this mean? Each thread has its own resources, just like in real life, every programmer has its own object, not to compete, absolute security thread ah. So ThreadLocal exactly how to use it?

Black question mark .png

Class 2 described

* This class provides thread-local variables.  These variables differ from
* their normal counterparts in that each thread that accesses one (via its
* {@code get} or {@code set} method) has its own, independently initialized
* copy of the variable.  {@code ThreadLocal} instances are typically private
* static fields in classes that wish to associate state with a thread (e.g.,
* a user ID or Transaction ID).

This is ThreadLocal class description above. Probably it means to provide a thread variable, usually modified static fields.

3 He created

Create a ThreadLocal There are two ways, one by the original no-argument constructor, the other is the use of lamaba expression Java8.

No argument constructor 3.1

Source

/**
 * Creates a thread local variable.
 * @see #withInitial(java.util.function.Supplier)
 */
public ThreadLocal() {
}

Use and initialize

private static final ThreadLocal<Integer> threadId = new ThreadLocal<Integer>() {
        @Override
        protected Integer initialValue(){
            return 1;
        }
    };

3.2 lamaba expression


    /**
     * Creates a thread local variable. The initial value of the variable is
     * determined by invoking the {@code get} method on the {@code Supplier}.
     *
     * @param <S> the type of the thread local's value
     * @param supplier the supplier to be used to determine the initial value
     * @return a new thread local variable
     * @throws NullPointerException if the specified supplier is null
     * @since 1.8
     */
    public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) {
        return new SuppliedThreadLocal<>(supplier);
    }

Use and initialize

private static final ThreadLocal<Integer> threadId = ThreadLocal.withInitial(() -> 1);

In fact, if you use IDEA to use it, the compiler will prompt may have lamaba. But take a look inside the source code was quite interesting.

4 getter () method

/**
 * Returns the value in the current thread's copy of this
 * thread-local variable.  If the variable has no value for the
 * current thread, it is first initialized to the value returned
 * by an invocation of the {@link #initialValue} method.
 *
 * @return the current thread's value of this thread-local
 */
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();
}

Here you can see Thread.currentThread, get the current thread, as well as ThreadLocalMap this class, he is a hash structure (key-value). getMap () method to get him through the current thread. By then again from this keyword as a key, the corresponding values ​​obtained value. Of course, if it is empty, it will return the value of initialization.

5 setter () method

Under what circumstances will not return the default value is initialized, the answer is to call the setter () methods. Look at the source

/**
 * Sets the current thread's copy of this thread-local variable
 * to the specified value.  Most subclasses will have no need to
 * override this method, relying solely on the {@link #initialValue}
 * method to set the values of thread-locals.
 *
 * @param value the value to be stored in the current thread's copy of
 *        this thread-local.
 */
public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}

Probably it means that the current thread as the key, the value to be set as the value placed on ThreadLocalMap this hash structure. See here, you know why ThreadLocal variables can provide a thread. He speaks stored separately from each thread, each thread has its own independent resources, resource sharing does not exist, so the thread safety.

6 Memory Leak

Each thread variables into a ThreadLocalMap inside, do not have memory problems. I'm part of the interception Source

static class ThreadLocalMap {
    static class Entry extends WeakReference<ThreadLocal<?>> {
        Object value;
        
        Entry(ThreadLocal<?> k, Object v) {
            super(k);
            value = v;
        }
    }
    
}

Here you can see the WeakReference this class, you know ThreadLocalMap class is a weak reference, Logically, generally executing the thread will be recycled garbage collection mechanism of the virtual machine. But is it really the right. If there is a thread pool environment, there has been a thread, then ThreadLocal will become a strong reference from, and can not be recovered. So there is a memory leak problem.

That now is remove () method when the appearances. Literally, be aware that this method can be cleared thread variable resources, the fact is true. So, at the end of the program, it is best to call it emove () method to prevent memory leaks.

reference

"High real Java concurrent programming"
ThreadLocal Source Generation

No micro-channel public attention, ready to move end reading

No public .jpg

Guess you like

Origin www.cnblogs.com/chenzhuantou/p/12005516.html