Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >枚举valueOf()的线程安全

枚举valueOf()的线程安全
EN

Stack Overflow用户
提问于 2012-08-16 04:33:32
回答 3查看 2.3K关注 0票数 1

这是一个永久的变化“冗长-如果或切换”的困境.

考虑使用静态方法的多线程应用程序,该方法包含一个长(十几个条件) if语句,该语句检查对象的类型并相应地返回值,例如

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static String checkType(Class<?> type)
{
    if (type == A.class)
    {
        return aString;
    }
    else if (type == B.class)
    {
        return bString;
    }
    ...
    else if (type == z.class)
    {
        return zString;
    }
}

显然,开关语句在这里并不直接适用,因此常见的模式是拥有一个enum并调用它的valueOf(),即执行以下操作

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public enum Strings
{
    A(aString), B(bString), ..., Z(zString)

    private final String value;

    private Strings(String value)
    {
        this.value = value;
    }

    public String value()
    {
        return this.value;
    }
}

因此,checkType()可以重写为

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static String checkType(Class<?> type)
{
    return Strings.valueOf(getActualTypeName(type.getClass().getName())).value();
}

通过对生产代码中添加的null值进行适当的检查,并在getActualTypeName()方法中对非原始类型进行一些字符串处理,以便从"class java.lang.Long"这样的字符串中检索实际的类型名称(对于原语,getName()方法返回预期的字符串,例如“long"”)。

但是,如果valueOf()不是线程安全的,那么在并发环境中这是行不通的。这同样适用于使用(正常) Map对象,这两个替代方案可能是相同模式的变体,因为enum.valueOf()显然是基于

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Enum.valueOf(Class<T> enumType, String name)

打电话

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
enumType.enumConstantDirectory().get(name);

Class.java类中。

每次调用enumConstantDirectory()方法时,都会返回从values()数组的副本创建的新HashMap

那是线安全吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-08-16 04:37:33

我找不到为什么enum.valueOf(String)不安全于线程的任何原因:

  • 字符串是不可变的,因此在valueOf完成其工作时不能对参数进行变异。
  • valueOf检查参数与枚举常量的名称,它们都是静态的和最终的

为什么您认为enum.valueOf()不是线程安全的呢?

编辑

valueOf调用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
T result = enumType.enumConstantDirectory().get(name);

其中enumType是您的枚举类。

enumConstantDirectory()使用此模式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Map<String, T> enumConstantDirectory() {
    if (enumConstantDirectory == null) {
        T[] universe = getEnumConstantsShared();
        if (universe == null)
            throw new IllegalArgumentException(
                getName() + " is not an enum type");
        Map<String, T> m = new HashMap<>(2 * universe.length);
        for (T constant : universe)
            m.put(((Enum<?>)constant).name(), constant);
        enumConstantDirectory = m;
    }
    return enumConstantDirectory;
}

其中enumConstantDirectory是一个可变变量:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private volatile transient Map<String, T> enumConstantDirectory = null;

假设一个线程以该方法并发到达:

  • 如果enumConstantDirectory为null (这里不存在可见性问题,因为它是易失性的),它将构造映射并将其赋值给该变量。由于不稳定的保证,所有其他线程,从那时起,将看到映射完全构建。
  • 如果另一个线程同时到达该方法并观察到enumConstantDirectory的空值,它将重新创建映射并再次安全地发布它。

最坏的情况是,两个线程可能使用两个不同的映射(不同的实例),但是它们的内容是相同的,因此不会引起任何问题。

底线:线程不可能看到一半构造的映射,因为映射构造是在局部变量上完成的,该局部变量在填充后分配给易失性变量

票数 5
EN

Stack Overflow用户

发布于 2012-08-16 04:38:20

没有理由认为Enum.valueOf()不是线程安全的。它不会变异任何东西,它只访问实际enum类中的状态,这实际上是最终的状态。

如果这个方法是非线程安全的,我认为javadocs中会有这样的内容。

票数 4
EN

Stack Overflow用户

发布于 2012-08-16 04:47:27

也许我错了,但这里似乎有一个微妙的问题:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static <T extends Enum<T>> T valueOf(Class<T> enumType,
                                                       String name) {
     T result = enumType.enumConstantDirectory().get(name);
     if (result != null)
           return result;
     if (name == null)
           throw new NullPointerException("Name is null");
     throw new IllegalArgumentException(
                     "No enum constant " + enumType.getCanonicalName() + "." + name);
}  

这是valueOf的代码。它使用传入的enumType创建具有常量的内部HashMap,代码不是sychronized

这里似乎有一个微妙的问题:T result = enumType.enumConstantDirectory().get(name);

enumConstantDirectory()检查enumConstantDirectory == null,但它不是同步的,以便创建HashMap。也许副作用并不重要(我不知道Class存储了什么信息),但无论如何,只要应用程序代码中没有共享enumType,它肯定是安全的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11987224

复制
相关文章
Java中枚举的线程安全性及序列化问题
要想看源码,首先得有一个类吧,那么枚举类型到底是什么类呢?是enum吗?答案很明显不是,enum就和class一样,只是一个关键字,他并不是一个类,那么枚举是由什么类维护的呢,我们简单的写一个枚举:
一个程序员的成长
2020/11/25
1.3K0
Java中枚举的线程安全性及序列化问题
String.valueOf()
1. 由 基本数据型态转换成 String String 类别中已经提供了将基本数据型态转换成 String 的 static 方法 也就是 String.valueOf() 这个参数多载的方法 有下列几种 String.valueOf(boolean b) : 将 boolean 变量 b 转换成字符串 String.valueOf(char c) : 将 char 变量 c 转换成字符串 String.valueOf(char[] data) : 将 char 数组 data 转换成字符串
猿人谷
2018/01/17
8730
valueOf与toString
valueOf和toString是Object.prototype上的方法,在Js几乎所有的对象都会继承自Object,同样由于包装对象的原因,几乎所有的数据类型都能够调用这两个方法,无法调用的有例如null、undefined以及Object.create(null)创建的对象等,通常我们一般不会主动调用这两个方法,而在代码执行的过程中这两个方法会经常被偷偷的调用,而且在不同的情况下会有选择的进行调用。
WindRunnerMax
2020/10/30
1.1K0
线程安全的queue-浅谈线程安全那些事儿
  在并发编程时,如果多个线程访问同一资源,我们需要保证访问的时候不会产生冲突,数据修改不会发生错误,这就是我们常说的 线程安全 。
宜轩
2022/12/29
4780
哪些线程是安全的_redis是线程安全的吗
Java中平时用的最多的map就是hashmap但是它却是线程不安全的。 那除了hashmap还有哪些常见的线程安全的map? 1.hashtable Map<String,Object> hashtable=new Hashtable<String,Object>();
全栈程序员站长
2022/08/03
1.2K0
CoreData的线程安全
1.没有线程安全的coredata数据读取: NSManagedObjectContext对象的创建: _managedObjectContext = [[NSManagedObjectContext alloc] init]; 2.线程安全的coreData操作: 1,创建并行的NSManagedObjectContext对象: [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType
rectinajh
2018/05/17
8260
多线程---线程安全
一、思考:线程安全产生的原因是什么? 二、final,volatile关键字的作用? 三、1.5之前的javaDCL有什么缺陷? 四、如何编写线程安全的程序? 五、ThreadLocal使用的注意事项有哪些?
用户9854323
2022/06/25
6050
多线程---线程安全
【Java】parseInt() 和valueOf() toString()的区别
就是把String类型转化为int类型。 如 String a= “123”; int b = Integer.parseInt(a); 这样b就等于123了。
瑞新
2020/12/07
9870
线程与线程安全
电脑中时会有很多单独运行的程序,每个程序有一个独立的进程,而进程之间是相互独立存在的。比如下图中的QQ、酷狗播放器、电脑管家等等。
狼啸风云
2019/11/28
7010
线程安全
在 Java 程序中,存储数据的内存空间分为共享内存和本地内存。线程在读写主存的共享变量时,会先将该变量拷贝一份副本到自己的本地内存,然后在自己的本地内存中对该变量进行操作,完成操作之后再将结果同步至主内存。
Qwe7
2022/08/06
4260
java中线程安全的容器_jfinal容器线程安全吗
Java编码中,我们经常需要用到容器来编程。在并发环境下,Java提供一些已有容器能够支持并发。
全栈程序员站长
2022/10/02
7070
java中线程安全的容器_jfinal容器线程安全吗
【Java】线程、线程安全、线程状态
昨天的时候我们已经写过一版多线程的代码,很多同学对原理不是很清楚,那么我们今天先画个多
陶然同学
2023/02/27
1.7K0
【Java】线程、线程安全、线程状态
线程安全
又名 AQS 框架,位于 java.util.concurrent.locks 包内。用来构建锁和同步器的框架,使用 AQS 能简单且高效地构造出应用广泛的大量的同步器,比如我们提到的 ReentrantLock,Semaphore 等。
Qwe7
2022/08/07
3700
线程安全
当一个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方法进行任何其他协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象是线程安全的。 线程安全的代码都必须具备一个特征:代码本身封装了所有必要的正确性保障手段(如互斥同步等),令调用者无需关心多线程的问题,更无须自己采取任何措施来保证多线程的正确调用。
栋先生
2018/09/29
1K0
线程安全
Java String.valueOf 的应用
题目:从键盘输入一个整数 n, 逆序输出数字。 package aaa; import java.io.BufferedInputStream; import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(new BufferedInputStream(System.in)); // 没有 new BufferedInputStream
Lokinli
2023/03/09
3370
js中的valueOf与toString
所有对象继承了两个转换方法: 第一个是toString(),它的作用是返回一个反映这个对象的字符串 第二个是valueOf(),它的作用是返回它相应的原始值 一般来说,对象到字符串的转换经过了如下步骤: 1.如果对象具有toString()方法,则调用这个方法。如果它返回一个原始值,js将这个值转换成字符串,并返还这个字符串结果。 2.如果对象没有toString()方法,或者这个方法并不返回一个原始值,那么js将调用valueOf()方法。 3.否则,js无法从toString()或者valueOf()获
windseek
2018/05/15
1.3K0
什么是线程安全?如何保证线程安全?
线程安全: 线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。 线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。 如何保证呢: 1、使用线程安全的类; 2、使用synchronized同步代码块,或者用Lock锁; > 由于线程安全问题,使用synchronized同步代码块 原理:当两个并发线程访问同一个对象object中
麦克劳林
2018/09/11
7.4K0
关于Javascript中的valueOf与toString
toString()函数的作用是返回object的字符串表示。 JavaScript中object默认的toString()方法返回字符串”[object Object]“。定义类时可以实现新的toString()方法,从而返回更加具有可读性的结果。 JavaScript对于数组对象、函数对象、正则表达式对象以及Date日期对象均定义了更加具有可读性的toString()方法:
Clearlove
2019/08/29
9420
什么时候线程不安全?怎样做到线程安全?怎么扩展线程安全的类?
当多个线程去访问某个类时,如果类会表现出我们预期出现的行为,那么可以称这个类是线程安全的。
爬蜥
2019/07/09
1.1K0
点击加载更多

相似问题

枚举型线程安全

14

线程安全列表的枚举?

235

NSArray的线程安全枚举

22

枚举valueOf IllegalArgumentException:没有枚举常量类

20

枚举器和线程安全

26
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文