# 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>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://jun-wang.gitbook.io/learnjava/ji-shu-xue-xi/java-duo-xian-cheng/threadlocal.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
