以下枚举验证程序线程是否安全?

时间:2015-06-18 18:24:19

标签: java generics enums bean-validation

我已经在这里的旧帖子后面实现了一个枚举验证器。我想知道以下代码是否是线程安全的?我有许多不同的枚举,我需要使用这个验证器。这会产生任何问题吗?

@Documented
@Constraint(validatedBy = StringEnumerationValidator.class)
@Target({ElementType.FIELD,ElementType.ANNOTATION_TYPE,
ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@NotNull(message="Value must not be null.")
public @interface StringEnumeration {

    String message() default "{com.xxx.bean.validation.constraints.StringEnumeration.message}";
    Class<?>[] groups() default{};
    Class<? extends Payload>[] payload() default{};
    Class<? extends Enum<?>> enumClass();
}


public class StringEnumerationValidator implements
    ConstraintValidator<StringEnumeration, String> {

    private Set<String> AVAILABLE_ENUM_NAMES;

    public static Set<String> getNamesSet(Class<? extends Enum<?>> e){
        Enum<?>[] enums = e.getEnumConstants();
        String[] names = new String[enums.length];
        for (int i = 0; i < enums.length; i++) {
            names[i] = enums[i].name();
            System.out.println(enums.length);
            System.out.println(enums[i]);
        }
        Set<String> mySet = new HashSet<String>(Arrays.asList(names));
        return mySet;
    }

    @Override
    public void initialize(StringEnumeration stringEnumeration) {
        Class<? extends Enum<?>> enumSelected =   stringEnumeration.enumClass();
        AVAILABLE_ENUM_NAMES = getNamesSet(enumSelected);

    }
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null) {
        return true;
        }
        else {
            return AVAILABLE_ENUM_NAMES.contains(value);
        }

  }

编辑:来源提及:

1 个答案:

答案 0 :(得分:0)

是和否。严格来说,它不是线程安全的,因为您的initialize方法可以由两个不同的线程同时调用。此方法写入AVAILABLE_ENUM_NAMES变量,因此两个线程可能会相互干扰。

但是如果你确保每个实例只调用initialize一次,那么在其他线程有权访问该实例之前,它是线程安全的,因为isValid只读取集合并且不修改它

要确保只进行一次初始化,您应该在构造函数中执行:

public StringEnumeratorValidator(StringEnumeration stringEnumeration) {
    Class<? extends Enum<?>> enumSelected = stringEnumeration.enumClass();
    AVAILABLE_ENUM_NAMES = getNamesSet(enumSelected);
}

并删除intialize方法。