Town building (you after the outbreak ends. JPG)

preface

Work at home 💻, dare not go out 🚪, dare not haircut 💇

Yes, like everyone else, this is what we will look like when the pandemic is over.

Also, haven’t you washed your hair in days?

Without further ado ~

This article is based on a problem from memory, implementing a ThreadLocal.

When the author encounters this problem for the first time, but very naive at that time, minute wrote, the result discovers is a low match edition, please also continue to look, have as naive as the author lead.

The body of the

Low configuration ThreadLocal implementation

In life, want to know where the advantages of a thing, how to do?

I don’t think most people will understand. However, when comparable products are made, the advantages and disadvantages are obvious. Again, I’ll use my humble MyThreadLocal to see what ThreadLocal is good for.


I haven’t read the source code of ThreadLocal carefully, but I still have a few keywords in mind: Map, weak reference, so I wrote a version of ThreadLocal.

public class ThreadLocal<T> {

    private Map<Thread, T> threadValMap = Collections.synchronizedMap(new WeakHashMap<>());
    
    public void set(T value) {
        threadValMap.put(Thread.currentThread(), value);
    }

    public T get() {
        return threadValMap.get(Thread.currentThread());
    }

    // remove....
}
Copy the code

After the Thread is used up, the reference is removed and the GC is notified. After a while, the key value is successfully reclaimed.

But looking at the source code of ThreadLocal itself, the design is quite different.

What’s the difference between this low edition and the regular edition?

Compare two ThreadLocal

I’ll call my self-implemented ThreadLocal MyThreadLocal for the rest of this article.

MyThreadLocal is a simple implementation that implements a synchronous weak-referenced HashMap with the synchronizedMap method.

I’ve also drawn a sketch of how ThreadLocal works internally:

One difference: efficiency

Due to the design Thread class lines brought a ThreadLocal. ThreadLocalMap threadLocals = null; As an attribute.

If ThreadLocalMap is empty, create one. If ThreadLocalMap is not empty, use it.

The two paragraphs above describe the first difference between MyThreadLocal and ThreadLocal:

SynchronizedMap synchronizedMap synchronizedMap synchronizedMap synchronizedMap synchronizedMap synchronizedMap synchronizedMap synchronizedMap

ThreadLocal, however, does not operate synchronously. Instead, it operates only on its current thread, which is naturally thread-closed. Using DB design as an analogy, it can be roughly analogous to this scenario:

“Add a field to a single table and you’re done. You have to build a relational table, and you have to pay attention to transactions.”

Of course, the DB design is different, so that performance can be determined, and we should also be careful when single-process coding, using immutable objects and thread closure, performance is better than synchronization and locking.

The second difference is the Key type of the Map

As you can see from the above image, MyThreadLocal’s Map uses Thread as the Key directly, while ThreadLocal’s Map uses itself.

As I mentioned above, Thread is directly used as the weak reference Key, and GC also successfully recycled, so what is the difference?

The difference is that you can only use new Thread() when testing;

In practice, threads are managed by a Thread pool, which uses Thread reuse internally. Therefore, threads are always referenced and cannot be discarded by GC, which may lead to memory leaks.

ThreadLocal has a similar problem, because in most cases we use static references to ThreadLocal and keep strong references all the time. Fortunately, ThreadLocal provides the remove method, which can be invoked only after the developer is careful to use it.

The last

The author wrote MyThreadLocal, a low-spec version of ThreadLocal at that time, and I know the advantages of ThreadLocal. I also feel that there is an interesting detail:

ThreadLocalMap does not use a HashMap internally, and instead writes a HashMap by hand.

When I looked at the ThreadLocalMap code at the time, I thought they were trying to show off their data structure skills. In fact, hashMap was invented later than ThreadLocalMap, which was one of the reasons why it didn’t work.

Think about it, Doug Lea and Josh Bloch at this level, still use show basics 😄…