关于使用ThreadLocals包装可变单例对象的建议

时间:2013-02-09 09:32:33

标签: java multithreading thread-local

来自Java Concurrency in practice第3.3.3章。的的ThreadLocal

  

线程局部变量通常用于防止设计中的共享   基于可变的单身人士或全局变量。

如果我们在ThreadLocal中包装可变的Singleton人,每个线程都有自己的Singleton副本?那么它将如何保持单身?这是作者的意思还是我错过了一些非常明显的东西?

3 个答案:

答案 0 :(得分:2)

  

如果我们在ThreadLocal中包装可变的Singleton人

AFAIK你不用ThreadLocal包装singleton类,但是包含在 mutable 或非线程安全的单例中的对象。正如该示例正确讨论的那样, JDBC连接不是线程安全的,并且需要额外的保护,这反过来会增加争用。

因此,在Singletons仅用于共享目的的情况下,然后用ThreadLocal替换这些东西是一个好主意,因为所有线程都有自己的Connection,并且不再需要额外的保护。

ThreadLocal用例的其他一个很好的例子是随机生成,如果有一个Random对象,那么“种子”的线程内存在争用,所以如果每个线程都有自己的Random对象,那么就不再存在争用了,这是有道理的。

答案 1 :(得分:0)

如果在ThreadLocal中包装Singleton(作为设计模式),它将保持为Singleton。如果你检查ThreadLocal的源代码,那么ThreadLocal中没有大的魔力。它使用Map并使用当前线程作为键。因此,在ThreadLocal中放置一个Singleton(一个实现良好的一个)是没有用的。因为你只能以各种方式获得相同的单身人士。

我认为作者意味着如果你的设计大量使用单例和/或全局变量,那么ThreadLocal是一个很好的选择,如果你需要每个线程有一些独特的东西,并且不想一直沿着调用层次结构传递。但这件事与Singleton不同。当然你可以在你的Singleton中封装一个ThreadLocal,这样它就会有一些特定于线程的状态(但是我不再称之为Singleton)

答案 2 :(得分:0)

我对这一行的理解是,当一个应用程序的设计方式使Singleton类具有可变状态时,许多线程正在读取和写入将需要线程安全,因此您需要序列化对该状态的所有访问。您可以考虑在该可变单例上创建ThreadLocal。 (来自书:-) 例如,单线程应用程序可能会维护在启动时初始化的全局数据库连接,以避免必须将Connection传递给每个方法。由于JDBC连接可能不是线程安全的,因此使用全局连接而无需额外协调的多线程应用程序也不是线程安全的。通过使用ThreadLocal存储JDBC连接,如代码清单3.10中的ConnectionHolder,每个线程都有自己的连接。

private static ThreadLocal<Connection> connectionHolder= new ThreadLocal<Connection>() {
      public Connection initialValue() {
  return DriverManager.getConnection(DB_URL);
  }
 };
   public static Connection getConnection() {
     return connectionHolder.get();
     }