0

我偶尔会收到ConcurrentModificationException以下代码:

public Set<MyObject> getTypes(Set<Type> names) {
        Set<MyObject> myObjects = new HashSet<>();          
        myObjects = names.stream().filter(Objects::nonNull).mapToInt(Type::getId)
                .mapToObj(cache::getMyObject)
                .collect(Collectors.toSet());

我正在使用缓存转换为MyObject,但方法中似乎抛出了异常collect(DAOImpl.java 第 114 行)

java.util.ConcurrentModificationException
        at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1558)
        at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
        at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
        at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
        at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
        at com.dao.DAOImpl.getTypes(DAOImpl.java:114)
        at com.dao.DAOImpl$$FastClassBySpringCGLIB$$affe23c4.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
        at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692)
        at com.dao.DAOImpl$$EnhancerBySpringCGLIB$$6000bd7e.getTypes(<generated>)

如何使用缓存映射到对象,还是必须在流外使用缓存?

通知缓存应该每天只更新 1 次

4

1 回答 1

0

该问题与您的cache::getMyObject. 问题是您的namesSet 在您流式传输时正在更改,因此ConcurrentModificationException.

如果您从您的names收藏中包装(创建一个新收藏)问题就解决了。

public Set<MyObject> getTypes(Set<Type> names) {
        Set<MyObject> myObjects = new HashSet<>(names).stream().filter(Objects::nonNull).mapToInt(Type::getId)
                .mapToObj(cache::getMyObject).collect(Collectors.toSet());

尽管如此,我认为您的缓存方法(getMyObject)可以返回null。在这种情况下,您应该将它们过滤掉。

如果要触发异常,可以执行以下操作:

 public static void main(String[] args) {
    Set<String> names = new HashSet();

    names.add("a");
    names.add("b");

    Thread x = new Thread(){
      @Override
      public void run() {
        try {
          sleep(1000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }

        names.add("c");
      }
    };

    x.start();

    Set<Object> myObjects = new HashSet<>(names).stream().filter(Objects::nonNull).mapToInt(s -> s.hashCode()).mapToObj(i -> String.valueOf(i)).map(x1-> getx(x1)).collect(Collectors.toSet());

  }

  private static Object getx(String x) {

    try {
      Thread.sleep(2000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    return x;
  }
于 2022-02-14T11:50:53.560 回答