Java ThreadLocal

ThreadLocal 类可以让你创建只被同一个线程读取和写入的变量,其他线程都不能做到,即使是在多个线程执行的是同一段代码的情况下,这些线程都不能看到彼此的 ThreadLocal 变量域。

创建 ThreadLocal

private ThreadLocal myThreadLocal = new ThreadLocal();

每个线程实例化一次 ThreadLocal 对象。这样即使是多个线程执行同一段代码访问同一个 ThreadLocal 变量,但是每个线程只能看到私有的 ThreadLocal 实例。这样,即使不同的线程给同一个 ThreadLocal 对象设置不同的值,都对彼此不可见。

访问 ThreadLocal

设置值

myThreadLocal.set("A thread local value");

读取值

String threadLocalValue = (String) myThreadLocal.get();

ThreadLocal 泛型

你可以创建一个泛型化的 ThreadLocal,这样使用 get() 方法的时候,就不需要类型转换了。

private ThreadLocal<String> myThreadLocal = new ThreadLocal<String>();

这样,你就只能存储字符串类型的值了

myThreadLocal.set("Hello ThreadLocal");
String threadLocalValue = myThreadLocal.get();

ThreadLocal 初始值

因为 ThreadLocal 中的值只对当前线程可见,无法做到为 ThreadLocal 设置对所有线程可见的初始值。如果想为 ThreadLocal 设置一个对所有线程可见的初始值,可以创建一个 ThreadLocal 的子类,并重写 initialValue() 方法

private ThreadLocal myThreadLocal = new ThreadLocal<String>() {
	@Override
  	protected String initialValue() {
    	return "This is the initial value";
  	}
};

现在,所有线程都可以在调用 myThreadLocal.set() 方法之前去调用 myThreadLocal.get() 获取到同样的初始值了。

完整的 ThreadLocal 例子

public class ThreadLocalExample {
	
	public static class MyRunnable implements Runnable {
		
		private ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();
		
		@Override
		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 InterruptedException {
		MyRunnable sharedRunnableInstance = new MyRunnable();
		
		Thread thread1 = new Thread(sharedRunnableInstance);
		Thread thread2 = new Thread(sharedRunnableInstance);
		
		thread1.start();
		thread2.start();
		
		thread1.join();  // wait for thread 1 to terminate
		thread2.join();  // wait for thread 2 to terminate
	}
}

这两个线程都不能看到对方的值,所以它们 set/get 了不同的值。

InheritableThreadLocal

InheritableThreadLocalThreadLocal 的子类。与每个线程持有自己的 ThreadLocal 中的值不同,InheritableThreadLocal 允许一个线程创建的所有子线程访问父线程的值。

posted @ 2016-10-11 21:26  勇敢的少年啊  阅读(291)  评论(0编辑  收藏  举报