在实例变量中使用 ThreadLocal

2024-01-08

Do Java ThreadLocal如果变量用作实例变量,则它们会生成线程局部值(例如,在生成线程本地对象的方法中),或者它们必须始终是静态的吗?

作为一个例子,假设一个典型的场景,其中几个初始化非线程安全类的对象的成本很高,需要在单个静态初始化块中实例化,存储在单个类的静态变量中(例如,在Map数据结构),并从此用于许多不同线程的密集处理。

为了实现线程安全,显然必须传递每个静态对象的不同副本。例如,JavaDateFormat需要在不同线程之间安全使用的对象。

在网上可以找到的许多示例中,该方法似乎是分别声明每个ThreadLocal变量,实例化新对象initialValue()方法,然后使用get()方法来检索线程本地实例。

如果要创建数十或数百个这样的对象,并且每个对象都有自己的初始化参数,则这种方法不是很有效。例如,许多SimpleDateFormat每个对象都有不同的日期模式。

如果对象的实例化可以在每次迭代中产生不同值的循环中完成,则在通过正确初始化相应对象来创建每个值之后,将需要一种用于生成线程本地实例的通用方法。

基于上述,以下通用静态方法将不起作用,因为每次调用initialValue()时都会生成相同的引用:

// Each value is an object initialized prior to calling getLocal(...)
public static final <T> T getLocal(final T value)
{
    ThreadLocal<T> local = new ThreadLocal<T>()
    {
        @Override
        protected T initialValue()
        {
            return value;
        }
    };

    return local.get();
}

相反,需要一种在initialValue() 内创建新对象的机制。因此,唯一通用的方法可能是使用反射,其模式类似于

private static final <T> T getLocal(
        final Constructor<T> constructor, final Object[] initargs)
{
    ThreadLocal<T> local = new ThreadLocal<T>()
    {           
        @Override
        protected T initialValue()
        {
            T value = null;

            try // Null if the value object cannot be created
            {
                value = constructor.newInstance(initargs);
            }
            catch (Exception e)
            {
            }

            return value;
        }
    };

    return local.get();
}

当然,还有特定于类型的选项,人们可以只使用ThreadLocal循环中用于声明每个变量的模式。

例如,在以下情况DateFormat,在单个静态初始化块中,可以这样做

private static String[] patterns = ... // Get date patterns
private static DateFormat format;

public static Map<String, DateFormat> formats = new HashMap<String, DateFormat>();

static
{
    for (final String pattern:patterns)
    {
        format = new ThreadLocal<DateFormat>()
        {           
                @Override
            protected DateFormat initialValue()
                {
            return new SimpleDateFormat(pattern);
            }
        }.get();

        formats.put(pattern, format);
}

从此,formats每次,map 都会被不同的类、不同的线程读取,以便调用format() or parse()一种或多种方法DateFormat存储在地图中的对象。

上述任何方法对于所描述的情况是否有意义,或者应该ThreadLocal声明是静态的吗?


为了回答你的标题问题,ThreadLocal为每个线程提供一个单独的值of that ThreadLocal实例。因此,如果您在不同的位置有两个实例,则每个线程将具有单独的值。这就是为什么ThreadLocals 通常是静态的;如果您想要的只是每个线程的变量的单独值,那么您只需要一个ThreadLocal对于 JVM 中的该变量。

A.H.的回答 https://stackoverflow.com/a/9655061/116639非常好,我会建议对其进行进一步的修改。看起来您可能希望将对日期格式的控制放在调用代码中,而不是放在地图的定义中。您可以使用如下代码来做到这一点:

public class DateFormatSupplier {
    private static final Map<String, ThreadLocal<DateFormat>> localFormatsByPattern = new HashMap<String, ThreadLocal<DateFormat>>();

    public static DateFormat getFormat(final String pattern) {
        ThreadLocal<DateFormat> localFormat;
        synchronized (localFormatsByPattern) {
            localFormat = localFormatsByPattern.get(pattern);
            if (localFormat == null) {
                localFormat = new ThreadLocal<DateFormat>() {
                    @Override
                    protected DateFormat initialValue() {
                        return new SimpleDateFormat(pattern);
                    }
                };
                localFormatsByPattern.put(pattern, localFormat);
            }
        }
        return localFormat.get();
    }
}

您在哪里创建ThreadLocal是懒惰的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在实例变量中使用 ThreadLocal 的相关文章

  • Jackson JSON + Java 泛型

    我正在尝试将以下 JSON 反序列化 映射到List
  • 同一服务器上的许多应用程序具有相同的 JMX Mbean 类

    我有超过 5 个 Spring Web 应用程序 它们都在使用另一个通用库 这个公共库有它自己的 MBean 由于强制的唯一 objectName 约束 我的应用程序无法部署在同一服务器上 我使用 MBean 的方式是这样的 Managed
  • 连接外部 Accumulo 实例和 java

    我正在尝试使用 Accumulo 连接到虚拟机 问题是 我无法将其连接到 Java 中 我可以看到 Apache 抛出的网页 但我无法让它与代码一起工作 我认为这是缺乏知识的问题而不是真正的问题 但我找不到这方面的文档 所有示例都使用 lo
  • 在不支持 CAS 操作的处理器上进行 CompareAndSet

    今天 我在一次采访中被问到下一个问题 如果您在具有不支持 CAS 操作的处理器的机器上调用 AtomicLong 的compareAndSet 方法 会发生什么情况 您能否帮我解决这个问题 并在可能的情况下提供一些全面描述的链接 From
  • 使用 OkHttp 下载损坏的文件

    我编写的下载文件的方法总是会产生损坏的文件 public static String okDownloadToFileSync final String link final String fileName final boolean te
  • 在 Spring 中为 @Pathvariable 添加类级别验证

    在发布这个问题之前 我已经做了很多研究并尝试了很多可用的解决方案 这是我陷入的棘手情况 我有一个 Spring 控制器 它有多个请求映射 它们都有 PathVariables 控制器如下所示 Controller EnableWebMvc
  • 为什么在将 String 与 null 进行比较时会出现 NullPointerException?

    我的代码在以下行中出现空指针异常 if stringVariable equals null 在此语句之前 我声明了 stringVariable 并将其设置为数据库字段 在这个声明中 我试图检测该字段是否有null值 但不幸的是它坏了 有
  • 使用 JDBC 连接到 PostgreSql 的本地实例

    我在 Linux 机器上有一个正在运行的 PostgreSql 本地实例 当我使用psql来自 shell 的命令我成功登录 没有任何问题 我需要通过 JDBC 连接到 PostgreSql 但我不知道我到底应该传递什么url参数为Driv
  • 无需递归即可对可观察结果进行分页 - RxJava

    我有一个非常标准的 API 分页问题 您可以通过一些简单的递归来处理 这是一个捏造的例子 public Observable
  • IntelliJ Idea:将简单的 Java servlet(无 JSP)部署到 Tomcat 7

    我尝试按照教程进行操作here http wiki jetbrains net intellij Creating a simple Web application and deploying it to Tomcat部署 servlet
  • 类更改(例如字段添加或删除)是否保持 Serialized 的向后兼容性?

    我有一个关于 Java 序列化的问题 在这种情况下 您可能需要修改可序列化类并保持向后兼容性 我有丰富的 C 经验 所以请允许我将 Java 与 NET 进行比较 在我的Java场景中 我需要使用Java的运行时序列化机制序列化一个对象 并
  • Joshua Bloch 的构建器设计模式有何改进?

    早在 2007 年 我就读过一篇关于 Joshua Blochs 所采用的 构建器模式 的文章 以及如何修改它以改善构造函数和 setter 的过度使用 特别是当对象具有大量属性 其中大部分属性是可选的 时 本文对此设计模式进行了简要总结
  • 为什么Apache MPM prefork.c 使用互斥体来保护accept()?

    我坐下来读书Apache 的 MPM prefork c http code metager de source xref apache httpd server mpm prefork prefork c这段代码使用了一个名为accept
  • Lombok 不适用于 Eclipse Neon

    我下载了lombok jar lombok 1 16 14 jar 并将其放入我的下载中 然后我点击这个 jar 执行正确地识别了我的 MacOS 上的 Eclipse 实例 然后我选择了我想要的实例 Lombok也在pom xml中指定
  • 用于请求带有临时缓存的远程 Observable 的 RxJava 模式

    用例是这样的 我想暂时缓存最新发出的昂贵的Observable响应 但在它过期后 返回到昂贵的源Observable并再次缓存它 等等 一个非常基本的网络缓存场景 但我真的很难让它工作 private Observable
  • Android ScrollView,检查当前是否滚动

    有没有办法检查标准 ScrollView 当前是否正在滚动 方向是向上还是向下并不重要 我只需要检查它当前是否正在滚动 ScrollView当前形式不提供用于检测滚动事件的回调 有两种解决方法可用 1 Use a ListView并实施On
  • Java 的“&&”与“&”运算符

    我使用的示例来自 Java Herbert Schildt 的完整参考文献 第 12 版 Java 是 14 他给出了以下 2 个示例 如果阻止 第一个是好的 第二个是错误的 因此发表评论 public class PatternMatch
  • Spring 作为 JNDI 提供者?

    我想使用 Spring 作为 JNDI 提供程序 这意味着我想在 Spring 上下文中配置一个 bean 可以通过 JNDI 访问该 bean 这看起来像这样
  • 在会话即将到期之前调用方法

    我的网络应用程序有登录的用户 有一个超时 在会话过期之前 我想执行一个方法来清理一些锁 我已经实现了sessionListener但一旦我到达public void sessionDestroyed HttpSessionEvent eve
  • 关闭扫描仪是否会影响性能

    我正在解决一个竞争问题 在问题中 我正在使用扫描仪获取用户输入 这是 2 个代码段 一个关闭扫描器 一个不关闭扫描器 关闭扫描仪 import java util Scanner public class JImSelection publ

随机推荐

  • 发布实现接口的 F# 类时的反射/C# 键入错误

    我有一个用 C 编写的接口 但在用 F 实现它时 我注意到一些奇怪的地方 F 类必须先转换为接口 然后 C 才能使用它 转换后 WPF 无法读取其属性 绑定失败且 SNOOP 无法反映它 我可以用 C 代码包装该对象 一切正常 界面 pub
  • Deflate压缩块的结构

    我在理解 Deflate 算法时遇到困难 RFC 1951 https www rfc editor org rfc rfc1951 TL DR如何解析Deflate压缩块4be4 0200 我创建了一个包含字母和换行符的文件a n在里面
  • 我应该在 Objective C 中哪里初始化变量?

    在 Objective C 中 我应该覆盖 init 方法来初始化我的变量吗 如果变量是属性 我仍然可以通过通常的方式访问它们来设置其初始值吗 在 Objective C 中 我应该覆盖 init 方法来初始化我的变量吗 是的 具体来说 指
  • Rails 3“最后”方法从 ActiveRecord 输出返回错误结果

    我的控制器中有以下代码 items Item where user id gt 1 order updated at DESC limit 2 oldest item items last 出于某种原因 我猜测这与我最近升级到 Rails
  • 缓存控制的默认值是多少?

    我的问题是 有时浏览器会过度缓存某些资源 即使我已经修改了它们 但F5之后一切都很好 我整个下午都在研究这个案例 现在我完全理解了 Last Modified 或 Cache Control 的意义 我知道如何解决我的问题issue 只是
  • 如何使用 sed 删除从第一行开始到遇到模式 '[ERROR] -17-12-2015' 之前的行?

    我需要在遇到模式 ERROR 17 12 2015 之前删除从第一行到该行的行 目前我正在尝试以下命令 但不幸的是它没有找到模式本身 sed 1 ERROR 17 12 2015 d errLog 这里有什么问题吗 其次 上面的脚本还将删除
  • 如何在python中添加换行符?

    我刚刚用 python 编写了一个程序 但输出中的语句彼此太接近 那么如何在 python 中的两个语句之间添加换行符呢 您可以打印新行字符 print n numlines
  • Kafka 的 session.timeout.ms 和 max.poll.interval.ms 之间的区别

    AFAIK max poll interval ms 是在 Kafka 0 10 1 中引入的 然而 目前还不清楚什么时候我们可以同时使用 session timeout ms 和 max poll interval ms 考虑这样的用例
  • 从日期集合中查找平均日期 (Ruby)

    我有一个猜测表 每个猜测中都只有一个日期 我想知道如何将两个或多个日期转化为平均值 div 类似这样 但显然 Ruby 不允许我划分这两个日期 日期有点难用 你应该使用时间 尝试将日期转换为时间 require time foo time
  • 应用程序运行时 Xcode 4.5 选项卡消失

    更新 看起来每当 Xcode 4 5 开始运行应用程序时 查看 gt 隐藏选项卡栏 命令都会自动执行 这确实看起来像一个错误 这个单词tabs在这个问题中指的是我们在顶部看到的那个Xcode集成开发环境 不是 Cocoa Touch 中的标
  • 多个读取器和多个写入器(我的意思是多个)同步

    我正在开发一项功能 需要一种读 写锁的变体 该变体可以允许并发多个写入者 标准读 写锁允许多个读取器或单个写入器同时运行 我需要一个可以同时允许多个读者或多个作者的变体 因此 它永远不应该允许读者和作者同时存在 但是 可以同时允许多个作者或
  • 云计算和网格计算有什么区别? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 之间有哪些显着差异云计算 and 网格计算 两者的精确定义和目标应用领域是什么 我正在寻找概念见解和技术细节 Like 微软Azure是一个云操作系统
  • 如何获取 JavaFX 应用程序中的主 Stage?

    是否可以在正在运行的 JavaFX 应用程序中获取对主 Stage 的引用 这个问题的背景是我想编写一个库来操作另一种语言 Prolog 的JavaFX接口 为了做到这一点 我的图书馆需要访问主舞台 目标是 JavaFX 应用程序的程序员不
  • 如何在 Android 中从一组图像创建视频?

    我想调用一个函数并从图像列表中构建视频 然后将其保存在设备本地 public void CreateAndSaveVideoFile List
  • 如何比较两个 UNIX 命令的输出以找出差异?

    我不想创建新文件 我想完成类似的事情 cmd1 gt a cmd2 gt b cat a b b sort uniq u 但不使用文件 a 和 b Unix 实用程序通常是面向文件的 因此没有什么能完全满足您的需求 但是 zsh 可以使用以
  • ggplot2按常数因子进行轴变换

    在 ggplot2 密度图 geom 密度 中 我有以下 y 轴标签 0 000 0 005 0 010 0 015 0 020 将它们更改为类似的正确方法是什么 0 5 10 15 20 可能会自动在标签上添加 10 3 x 密度 过去
  • 如何将 ScrollView 与嵌套的 FlatList 一起使用?

    在主屏幕中 我有 3 个 FlatList 和一些其他视图的 其他数据 那么我应该将它包装在 ScrollView 中 这样我就可以滚动查看其他数据等等 但是当我用scrollView包装FlatList时我收到了这个警告 Virtuali
  • Firebase 自定义域名

    I m having a lot of trouble configuring my custom domain Currently if you go to my site www mydomain com it redirects to
  • 将 android EditText 样式从矩形边框更改为下划线

    在我的一项活动中 我的 EditText 视图过去看起来像这样 但现在他们看起来像这样 我需要帮助将其改回来 从矩形到下划线 背景 因为我需要创建一个自定义 ActionBar 所以我必须更改相关活动的主题 YesterdayActivit
  • 在实例变量中使用 ThreadLocal

    Do Java ThreadLocal如果变量用作实例变量 则它们会生成线程局部值 例如 在生成线程本地对象的方法中 或者它们必须始终是静态的吗 作为一个例子 假设一个典型的场景 其中几个初始化非线程安全类的对象的成本很高 需要在单个静态初