The ThreadLocal class can be understood as ThreadLocalVariable (thread local variable), which provides access interfaces or methods such as get and set. These methods store an independent copy for each thread that uses the variable, so get always returns the location of the current execution thread. The latest value set when calling set. ThreadLocal<T> can be thought of as containing a Map<Thread,T> object, holding values specific to that thread.
To sum up, for the problem of multi-thread resource sharing, the synchronization mechanism adopts the method of "exchanging time for space", while ThreadLocal adopts the method of "exchanging space for time". The former only provides a copy of the variable for different threads to queue for access, while the latter provides a copy of the variable for each thread, so it can be accessed at the same time without affecting each other.
Mock ThreadLocal
Copy the code code as follows:
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class SimpleThreadLocal<T> {
private Map<Thread, T> valueMap = Collections
.synchronizedMap(new HashMap<Thread, T>());
public void set(T newValue) {
valueMap.put(Thread.currentThread(), newValue); // ①The key is the thread object and the value is a copy of the variable of this thread
}
public T get() {
Thread currentThread = Thread.currentThread();
T o = valueMap.get(currentThread); // ② Return the variable corresponding to this thread
if (o == null && !valueMap.containsKey(currentThread)) { // ③If it does not exist in the Map, put it in the Map and save it.
o = initialValue();
valueMap.put(currentThread, o);
}
return o;
}
public void remove() {
valueMap.remove(Thread.currentThread());
}
protected T initialValue() {
return null;
}
}
UtilityThreadLocal
Copy the code code as follows:
class Count {
private SimpleThreadLocal<Integer> count = new SimpleThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
}
};
public Integer increase() {
count.set(count.get() + 1);
return count.get();
}
}
class TestThread implements Runnable {
private Count count;
public TestThread(Count count) {
this.count = count;
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 1; i <= 3; i++) {
System.out.println(Thread.currentThread().getName() + "/t" + i
+ "th/t" + count.increase());
}
}
}
public class TestThreadLocal {
public static void main(String[] args) {
Count count = new Count();
Thread t1 = new Thread(new TestThread(count));
Thread t2 = new Thread(new TestThread(count));
Thread t3 = new Thread(new TestThread(count));
Thread t4 = new Thread(new TestThread(count));
t1.start();
t2.start();
t3.start();
t4.start();
}
}
The output copy code is as follows:
Thread-0 1th 1
Thread-0 2th 2
Thread-0 3th 3
Thread-3 1th 1
Thread-1 1th 1
Thread-1 2th 2
Thread-2 1th 1
Thread-1 3th 3
Thread-3 2th 2
Thread-3 3th 3
Thread-2 2th 2
Thread-2 3th 3