# Java `ThreadLocal`示例

> 原文： [https://javatutorial.net/threadlocal-java-example](https://javatutorial.net/threadlocal-java-example)

`ThreadLocal`是提供线程局部变量的类，用于实现线程安全。 存储的数据只能由特定线程访问。

![java-featured-image](img/e0db051dedc1179e7424b6d998a6a772.jpg)

`ThreadLocal`扩展了`Object`类，并提供了线程限制，它是局部变量的“一部分”。

## 创建`ThreadLocal`变量

```java
ThreadLocal threadLocalExample = new ThreadLocal();
```

上面代码中`ThreadLocal`对象的实例化仅需要针对每个线程进行。

就像大多数类一样，一旦有了`ThreadLocal`的实例，就可以在其上调用方法。 一些方法是：

1.  `get()`：返回此线程局部变量的当前线程副本中的值
2.  `initialValue()`：返回当前线程局部变量的当前线程初始值
3.  `remove()`：从当前线程中删除当前线程局部变量的值
4.  `set(T value)`：将当前线程局部变量的当前线程副本设置为指定值

有关这些方法的更多详细信息，请访问原始 [Oracle 文档](https://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html)。

`ThreadLocal`实例是希望将状态与线程相关联的类中的私有静态字段（在大多数情况下）

## 实现示例

```java
public class ThreadLocalExample { 
    public static class Example implements Runnable {
        private ThreadLocal<String> example = new ThreadLocal<String>();
        // override the run() method that comes from implementing Runnable class
        @Override
        public void run() {
            try {
                System.out.println("Getting values...");
                Thread.sleep(2000);
            }
            catch (InterruptedException e) {  
                System.out.println(e);
            }  
            example.set("Just a random text that will be displayed before the remove function");
            System.out.println("Before remove: " + example.get());
            example.remove();
            System.out.println("After remove: " + example.get());
        }
    }
    public static void main(String[] args) { 
        /* EXAMPLE THAT DOES NOT HAVE TO DO ANYTHING WITH THE STATIC CLASS ABOVE main*/
        ThreadLocal<String> local = new ThreadLocal<String>(); 
        local.set("First"); 
        System.out.println("Value: " + local.get()); 

        local.set("Second"); 
        System.out.println("Value: " + local.get()); 

        local.remove(); 
        System.out.println("Value: " + local.get());
        /* NEW EXAMPLE THAT USES THE STATIC CLASS DECLARED ABOVE main */
        Example runnable = new Example();
        Thread thread = new Thread(runnable);
        thread.start();
    } 
}
```

**输出**

```java
Value: First
Value: Second
Value: null
Getting values...
Before remove: Just a random text that will be displayed before the remove function
After remove: null
```

## 分解

上面的代码显示了两种使它起作用的方法：一种是通过拥有`Runnable`对象并将其传递给`Thread`实例，然后覆盖`run()`方法，或者您可以简单地创建一个`ThreadLocal`实例并为其设置值，然后 可以获取或删除它。 从上面的示例中可以看到，即使它是相同的变量（局部变量），也可以包含不同的值。 在第一种情况下，它包含值`"First"`。 在第二种情况下，它包含值`"Second"`。 对于其他实现，我只显示了一个线程。 但是，每个线程都是独立的–意味着，如果您要创建另一个`Thread`实例（例如`thread2`），并对其进行`start()`，它将独立运行，并且与其他`Thread`实例变量无关。 要进行检查，可以在静态类中创建一个`ThreadLocal`实例，然后在重写的`run()`方法中创建一个随机数，然后使用`set()`方法将其传递给当前线程。 您将看到，如果您在两个或多个不同的线程上调用它，则它们都将具有不同的值。