Java中的ThreadLocal类使您可以创建只能由同一线程读取和写入的变量。 因此,即使两个线程正在执行相同的代码,并且代码具有对ThreadLocal变量的引用,那么这两个线程也看不到彼此的ThreadLocal变量。
下面是一个代码示例,演示如何创建ThreadLocal变量:
private ThreadLocal myThreadLocal = new ThreadLocal();
如您所见,您实例化一个新的ThreadLocal对象。 这只需要每个线程完成一次。 即使不同的线程执行访问ThreadLococal的相同代码,每个线程也只能看到自己的ThreadLocal实例。 即使两个不同的线程在同一个ThreadLocal对象上设置不同的值,它们也看不到彼此的值。
创建ThreadLocal后,您可以设置要存储在其中的值,如下所示:
myThreadLocal.set("A thread local value");
创建ThreadLocal后,您可以设置要存储在其中的值,如下所示:
String threadLocalValue = (String)myThreadLocal.get();
get()方法返回一个Object,set()方法将Object作为参数。
您可以创建一个通用的ThreadLocal,这样就不必对get()返回的值进行类型转换。 这是一个通用的ThreadLocal示例:
private ThreadLocal<String> myThreadLocal = new ThreadLocal<String>();
现在,您只能在ThreadLocal实例中存储字符串。 此外,您不需要对从ThreadLocal获取的值进行类型转换:
myThreadLocal.set("Hello ThreadLocla");
String msg = myThreadLocal.get();
由于在ThreadLocal对象上设置的值仅对设置值的线程可见,因此没有线程可以使用set()在ThreadLocal上设置初始值.
相反,您可以通过继承ThreadLocal并覆盖initialValue()方法来为ThreadLocal对象指定初始值。
private ThreadLocal myThreadLocal = new ThreadLocal<String>() {
@Override
protected String initialValue() {
return "This is the initial value";
}
};
现在,在调用set()之前调用get()时,所有线程都会看到相同的初始值。
这是一个完全可运行的Java ThreadLocal示例:
package concurrency;
public class ThreadLocalDemo {
public static class MyRunnable implements Runnable {
private ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
public void run() {
threadLocal.set((int)(Math.random() * 100D));
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println(threadLocal.get());
}
}
public static void main(String[] args) throws Exception {
MyRunnable myRunnable = new MyRunnable();
Thread thread1 = new Thread(myRunnable);
Thread thread2 = new Thread(myRunnable);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(Thread.currentThread().getName());
}
}
此示例创建一个MyRunnable实例,该实例将传递给两个不同的线程。 两个线程都执行run()方法,因此在ThreadLocal实例上设置不同的值。 如果对set()调用的访问已经同步,并且它不是ThreadLocal对象,则第二个线程将覆盖第一个线程设置的值。
InheritableThreadLocal类是ThreadLocal的子类。 InheritableThreadLocal不是每个线程在ThreadLocal中都有自己的值,而是授予该线程创建的所有子线程访问权限。
翻译自: http://tutorials.jenkov.com/java-concurrency/threadlocal.html
原作者: Jakob Jenkov