java - ThreadLocal 的目的?

标签 java multithreading thread-local

给定的 ThreadLocal 的用途 here声明该变量对于任何访问包含 ThreadLocal 变量的对象的线程都是本地的。将 ThreadLocal 变量作为类的成员,然后使其成为 Thread 的本地变量,而不是 Thread 本身的局部变量,这有什么区别?

最佳答案

线程是一个执行单元,因此多个线程可以同时执行相同的代码。如果多个线程同时在一个对象/实例上执行,它们将共享实例变量。每个线程都有自己的局部变量,但如果不传递参数,很难跨对象共享这些变量。

最好通过一个例子来解释。假设您有一个 Servlet,它获取登录用户,然后执行一些代码。

doGet(HttpServletRequest req, HttpServletResponse resp) {
  User user = getLoggedInUser(req);
  doSomething()
  doSomethingElse()
  renderResponse(resp)
}

现在如果 doSomething() 方法需要访问用户对象会发生什么?您不能将用户对象设为实例或静态变量,因为随后每个线程将使用相同的用户对象。您可以将用户对象作为参数传递,但这很快就会变得困惑并将用户对象泄漏到每个方法调用中:

doGet(HttpServletRequest req, HttpServletResponse resp) {
  User user = getLoggedInUser(req);
  doSomething(user)
  doSomethingElse(user)
  renderResponse(resp,user)
}

更优雅的解决方案是将用户对象放入 ThreadLocal

doGet(HttpServletRequest req, HttpServletResponse resp) {
  User user = getLoggedInUser(req);
  StaticClass.getThreadLocal().set(user)
  try {
    doSomething()
    doSomethingElse()
    renderResponse(resp)
  }
  finally {
    StaticClass.getThreadLocal().remove()
  }
}

现在任何需要用户对象的代码都可以通过从线程本地提取它来获取它,而无需求助于那些讨厌的额外参数:

User user = StaticClass.getThreadLocal().get()

如果您使用这种方法,请注意在 finally block 中再次删除对象。否则,用户对象可能会在使用线程池的环境(如 Tomcat 应用服务器)中徘徊。

编辑:静态类的代码

class StaticClass {
  static private ThreadLocal<User> threadLocal = new ThreadLocal<>();

  static ThreadLocal<User> getThreadLocal() {
    return threadLocal;
  }
}

关于java - ThreadLocal 的目的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1490919/

相关文章:

java - 如何在 JSF 数据表中获取选定的行索引?

java - 学习 Java 中的 Switch 语句

java - 将 select 语句放在 Hibernate 事务上

java - Spring 的线程

java - ThreadLocal是在TLAB中分配的吗?

java - 将 "current user"保留在 threadlocal 中

java - Swing 的 Unicode 支持的限制

c++ - 如何终止 std::thread?

python - 如何使用多线程加速嵌套for循环计算?

c++ - 锁定函数层次结构