# ThreadLocal

ThreadLocal用于保存某个线程共享变量，对于同一个static ThreadLocal，不同线程只能从中get，set，remove自己的变量，而不会影响其他线程的变量。

* ThreadLocal.get: 获取ThreadLocal中当前线程共享变量的值。
* ThreadLocal.set: 设置ThreadLocal中当前线程共享变量的值。
* ThreadLocal.remove: 移除ThreadLocal中当前线程共享变量的值。
* ThreadLocal.initialValue: ThreadLocal没有被当前线程赋值时或当前线程刚调用remove方法后调用get方法，返回此方法值。

举例：

```java

public class ThreadLocalTest {
	
	private static final ThreadLocal<Object> threadLocal = new ThreadLocal<Object>() {
		// ThreadLocal没有被当前线程赋值时或当前线程刚调用remove方法后调用get方法，返回此方法值
		protected Object initialValue() {
			System.out.println("调用get方法时，当前线程共享变量没有设置，调用initialValue获取默认值！当前线程" + Thread.currentThread().getName());
			return "";
		}; 
	};

	public static void main(String[] args) {
		new Thread(new MyThread()).start();
		new Thread(new MyThread()).start();
		new Thread(new MyThread()).start();
		new Thread(new MyThread()).start();
	}
	
	public static class MyThread extends Thread {
		
		@Override
		public void run() {
			for(int i = 0; i < 5; i++) {
				if("".equals(threadLocal.get())) {
					threadLocal.set("a");
				}else {
					threadLocal.set(threadLocal.get() + "a");
				}
				System.out.println("currentThread:" + Thread.currentThread().getName() + ":" + threadLocal.get());
			}
		}
	}
}

```

打印结果：

```shell
调用get方法时，当前线程共享变量没有设置，调用initialValue获取默认值！当前线程Thread-3
调用get方法时，当前线程共享变量没有设置，调用initialValue获取默认值！当前线程Thread-1
调用get方法时，当前线程共享变量没有设置，调用initialValue获取默认值！当前线程Thread-7
调用get方法时，当前线程共享变量没有设置，调用initialValue获取默认值！当前线程Thread-5
currentThread:Thread-5:a
currentThread:Thread-7:a
currentThread:Thread-1:a
currentThread:Thread-1:aa
currentThread:Thread-3:a
currentThread:Thread-1:aaa
currentThread:Thread-1:aaaa
currentThread:Thread-7:aa
currentThread:Thread-5:aa
currentThread:Thread-5:aaa
currentThread:Thread-5:aaaa
currentThread:Thread-5:aaaaa
currentThread:Thread-7:aaa
currentThread:Thread-1:aaaaa
currentThread:Thread-3:aa
currentThread:Thread-7:aaaa
currentThread:Thread-3:aaa
currentThread:Thread-7:aaaaa
currentThread:Thread-3:aaaa
currentThread:Thread-3:aaaaa

```

可以看到不同的线程调用同一个ThreadLocal变量的get方法返回值是不一样的（就是说互不影响，比如线程1将threadLocal设置成1，那么线程2get到的并一定是1，而是取决于线程2set的值）。那么原理是怎么实现的呢，我们看下set和get的源码：

```java
// set的时候，先获取当前线程，以当前线程做key查询map，然后对map进行新增和更新
public void set(T paramT)
  {
    Thread localThread = Thread.currentThread();
    ThreadLocalMap localThreadLocalMap = getMap(localThread);
    if (localThreadLocalMap != null) {
      localThreadLocalMap.set(this, paramT);
    } else {
      createMap(localThread, paramT);
    }
  }

// 同理，get的时候，也是先获取当前线程，以当前线程做key查询map
public T get()
  {
    Thread localThread = Thread.currentThread();
    ThreadLocalMap localThreadLocalMap = getMap(localThread);
    if (localThreadLocalMap != null)
    {
      ThreadLocal.ThreadLocalMap.Entry localEntry = localThreadLocalMap.getEntry(this);
      if (localEntry != null)
      {
        Object localObject = localEntry.value;
        return localObject;
      }
    }
    return setInitialValue();
  }
```

> 参考：
>
> <https://www.cnblogs.com/coshaho/p/5127135.html>
