The ThreadLocal class represents a thread local variable. By placing the data in ThreadLocal, each thread can create a copy of the variable. It can also be regarded as another way of thread synchronization. By creating a thread-local copy of a variable for each thread, it avoids conflicts when concurrent threads read and write the same variable resource at the same time.
Examples are as follows:
import java.util.Random;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;import com.sun.javafx.webkit.Accessor;public class ThreadLocalTest { static class ThreadLocalVariableHolder { private static ThreadLocal<Integer> value = new ThreadLocal<Integer>() { private Random random = new Random(); protected synchronized Integer initialValue() { return random.nextInt(10000); } }; public static void increment() { value.set(value.get() + 1); } public static int get() { return value.get(); } } static class Accessor implements Runnable{ private final int id; public Accessor(int id) { this.id = id; } @Override public void run() { while (!Thread.currentThread().isInterrupted()) { ThreadLocalVariableHolder.increment(); System.out.println(this); Thread.yield(); } } @Override public String toString() { return "#" + id + ": " + ThreadLocalVariableHolder.get(); } } public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) { executorService.execute(new Accessor(i)); } try { TimeUnit.MICROSECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } executorService.shutdownNow(); }}Running results:
#1: 9685#1: 9686#2: 138#2: 139#2: 140#2: 141#0: 5255. . .
From the running results, we can see that each thread is used for its own Local variables, and each reads and writes does not interfere with each other.
ThreadLocal provides three methods to operate, set, get and remove.
In Android, ThreadLocal is used to create separate Looper objects for each thread.
public final class Looper { private static final String TAG = "Looper"; // sThreadLocal.get() will return null unless you've called prepare(). static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); } . . . }When a thread needs its own Looper and message queue, it calls Looper.prepare(), which will create a Looper object and MessageQueue belonging to the thread for the thread, and save the Looper object in ThreadLocal.