【问题标题】:JSF Entityconverter ConcurrentModificationExceptionJSF Entityconverter ConcurrentModificationException
【发布时间】:2018-05-11 07:22:15
【问题描述】:

我在我的项目中使用通用实体转换器。 我注意到有时转换器会抛出 java.util.ConcurrentModificationException 还有一个4岁的Post没有答案。

我尝试使用 Iterator 而不是普通的 for-loop,但没有帮助。

有没有办法创建线程安全的转换器?

@FacesConverter(value = "entityConverter")
public class EntityConverter implements Converter {

    private static Map<Object, String> entities = new WeakHashMap<Object, String>();

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object entity) {
        synchronized (entities) {
            if (!entities.containsKey(entity)) {
                String uuid = UUID.randomUUID().toString();
                entities.put(entity, uuid);
                return uuid;
            } else {
                return entities.get(entity);
            }
        }
    }

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String uuid) {

        Iterator<Map.Entry<Object, String>> tempIt = entities.entrySet().iterator();
        while (tempIt.hasNext()) {
            Map.Entry<Object, String> nextObj = tempIt.next();
            if (nextObj.getValue().equals(uuid)) {
                return nextObj.getKey();
            }
        }

        return null;
    }

}

【问题讨论】:

    标签: java jsf


    【解决方案1】:

    与其他方法一样,将getAsObject 的主体包裹在与entities 同步的块中。

    【讨论】:

    • 非常感谢!我不知道为什么我没有先尝试!
    【解决方案2】:

    实现它的另一种方法是使用Java 的ConcurrentMap 以保证线程安全。单线:

    private static ConcurrentMap<Object, String> entities = new ConcurrentHashMap<>();
    
    @Override
    public String getAsString(FacesContext context, UIComponent component, Object entity) {
        return entities.putIfAbsent(entity, UUID.randomUUID().toString());
    }
    

    从 Java 8 开始,您还可以利用 computeIfAbsent,它只会在密钥不存在时计算 UUID:

    return entities.putIfAbsent(entity, 
        entities.computeIfAbsent(k -> UUID.randomUUID().toString()));
    

    如果您想保留弱引用,甚至可以使用 Guava's caching utilities 对其进行增强。

    【讨论】:

    • 最好使用computeIfAbsent,所以你只在必要时计算一个新的uuid。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-06
    • 2023-03-03
    相关资源
    最近更新 更多