原文: https://javatutorial.net/threadlocal-java-example

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

Java `ThreadLocal`示例 - 图1

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

创建ThreadLocal变量

  1. ThreadLocal threadLocalExample = new ThreadLocal();

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

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

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

有关这些方法的更多详细信息,请访问原始 Oracle 文档

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

实现示例

  1. public class ThreadLocalExample {
  2. public static class Example implements Runnable {
  3. private ThreadLocal<String> example = new ThreadLocal<String>();
  4. // override the run() method that comes from implementing Runnable class
  5. @Override
  6. public void run() {
  7. try {
  8. System.out.println("Getting values...");
  9. Thread.sleep(2000);
  10. }
  11. catch (InterruptedException e) {
  12. System.out.println(e);
  13. }
  14. example.set("Just a random text that will be displayed before the remove function");
  15. System.out.println("Before remove: " + example.get());
  16. example.remove();
  17. System.out.println("After remove: " + example.get());
  18. }
  19. }
  20. public static void main(String[] args) {
  21. /* EXAMPLE THAT DOES NOT HAVE TO DO ANYTHING WITH THE STATIC CLASS ABOVE main*/
  22. ThreadLocal<String> local = new ThreadLocal<String>();
  23. local.set("First");
  24. System.out.println("Value: " + local.get());
  25. local.set("Second");
  26. System.out.println("Value: " + local.get());
  27. local.remove();
  28. System.out.println("Value: " + local.get());
  29. /* NEW EXAMPLE THAT USES THE STATIC CLASS DECLARED ABOVE main */
  30. Example runnable = new Example();
  31. Thread thread = new Thread(runnable);
  32. thread.start();
  33. }
  34. }

输出

  1. Value: First
  2. Value: Second
  3. Value: null
  4. Getting values...
  5. Before remove: Just a random text that will be displayed before the remove function
  6. After remove: null

分解

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