“PK creative Spring Festival, I am participating in the” Spring Festival Creative submission contest “, please see: Spring Festival Creative Submission Contest”
How ThreadLocal works
We all know that Android does not allow UI updates from threads other than the main thread (the UI thread), on the one hand, if the UI can be modified, the UI components must be locked, which causes design headaches, and on the other hand, threads can block, resulting in a loss of efficiency. So we usually pass tasks to the main thread using a Handler that handles UI updates. How does this work? We need a special data store class called ThreadLocal
private ThreadLocal<Integer> mIntegerThreadLocal = new ThreadLocal<>();
Copy the code
This data store class stores data based on a specific thread.
public class MainActivity extends AppCompatActivity {
private ThreadLocal<Integer> mIntegerThreadLocal = new ThreadLocal<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
mIntegerThreadLocal.set(1);
new Thread(new Runnable() {
@Override
public void run(a) {
mIntegerThreadLocal.set(0);
Log.d("Thread0".""+mIntegerThreadLocal.get());
}
}).start();
try{
Thread.sleep(1000);
}catch (Exception e){
e.printStackTrace();
}
Log.d("mainThread".""+mIntegerThreadLocal.get());
super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }}Copy the code
The result of the program output aboveYou can see that although the same ThreadLocal exists, different threads do not interact with each other. How does ThreadLocal store data to the corresponding thread?
Within each thread will have a ThreadLocal ThreadLocalMap types of data, called threadLocals
When data needs to be stored in ThreadLocal, it will eventually be stored in threadLocals of the thread. . Then we went to see a ThreadLocal ThreadLocalMap class of concrete structure
An Entry class and an Entry array type can be found in the table, where the Entry class is defined as follows:
static class Entry extends WeakReference<ThreadLocal<? >>{
/** The value associated with this ThreadLocal. */Object value; Entry(ThreadLocal<? > k, Object v) {super(k); value = v; }}Copy the code
Entry inherits from WeakReference
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if(map ! =null)
map.set(this, value);
else
createMap(t, value);
}
Copy the code
Get the ThreadLocals from the Thread and save the data. Then look at
private void set(ThreadLocal
key, Object value) {
// We don't use a fast path as with get() because it is at
// least as common to use set() to create new entries as
// it is to replace existing ones, in which case, a fast
// path would fail more often than not.
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(); }Copy the code
This process iterates through the table array we mentioned earlier, comparing the ThreadLocal points to the same, and assigning if so. So that’s about it, set, and then get
public T get(a) {
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;
returnresult; }}return setInitialValue();
}
Copy the code
This process is also very simple, that is, call the ThreadLocal of this method to get the corresponding Entry, and then get the value naturally.
conclusion
As a whole, we defined the ThreadLocal is just a teaser, real data storage place in each thread corresponding ThreadLocal. ThreadLocals ThreadLocalMap type of data, However, it is important to remember that each thread may have more than one ThreadLocal, so we set an Entry type data in the ThreadLocalMap to place data for each ThreadLocal