Java java.util.ConcurrentModificationException错误

时间:2010-04-26 07:48:33

标签: java core

请允许任何人帮我解决这个问题,这么多天我无法解决这个错误。我尝试使用同步方法和其他方法,但没有工作,所以请帮助我

错误

java.util.ConcurrentModificationException
 at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
 at java.util.AbstractList$Itr.remove(Unknown Source)
 at JCA.startAnalysis(JCA.java:103)
 at PrgMain2.doPost(PrgMain2.java:235)

代码

 public synchronized void startAnalysis() {
        //set Starting centroid positions - Start of Step 1
        setInitialCentroids();
        Iterator<DataPoint> n = mDataPoints.iterator();
        //assign DataPoint to clusters
        loop1:
        while (true) {
            for (Cluster c : clusters)
            {
                c.addDataPoint(n.next());
                if (!n.hasNext())
                    break loop1;
            }
        }

        //calculate E for all the clusters
        calcSWCSS();

        //recalculate Cluster centroids - Start of Step 2
        for (Cluster c : clusters) {
            c.getCentroid().calcCentroid();
        }

        //recalculate E for all the clusters
        calcSWCSS();


       // List copy = new ArrayList(originalList);

        //synchronized (c) {

        for (int i = 0; i < miter; i++) {
            //enter the loop for cluster 1

         for (Cluster c : clusters) {


                for (Iterator<DataPoint> k = c.getDataPoints().iterator(); k.hasNext(); ) {
             //    synchronized (k) {

                 DataPoint dp = k.next(); 


                    System.out.println("Value of DP" +dp);
                    //pick the first element of the first cluster
                    //get the current Euclidean distance
                    double tempEuDt = dp.getCurrentEuDt();
                    Cluster tempCluster = null;
                    boolean matchFoundFlag = false;

                    //call testEuclidean distance for all clusters
                    for (Cluster d : clusters) {

                        //if testEuclidean < currentEuclidean then
                        if (tempEuDt > dp.testEuclideanDistance(d.getCentroid())) {
                            tempEuDt = dp.testEuclideanDistance(d.getCentroid());
                            tempCluster = d;
                            matchFoundFlag = true;
                        }
                        //if statement - Check whether the Last EuDt is > Present EuDt

                    }
                    //for variable 'd' - Looping between different Clusters for matching a Data Point.
                    //add DataPoint to the cluster and calcSWCSS

                    if (matchFoundFlag) {
          tempCluster.addDataPoint(dp);

         //k.notify();  
     //     if(k.hasNext())
          k.remove();


          for (Cluster d : clusters) {
                            d.getCentroid().calcCentroid();
                        }

                        //for variable 'd' - Recalculating centroids for all Clusters

                        calcSWCSS();
                  }

                    //if statement - A Data Point is eligible for transfer between Clusters.
                // }// syn
                 }                 
                //for variable 'k' - Looping through all Data Points of the current Cluster.
            }//for variable 'c' - Looping through all the Clusters.
        }//for variable 'i' - Number of iterations.
     // syn
    }

4 个答案:

答案 0 :(得分:8)

您在迭代时无法修改列表,除非您通过Iterator执行此操作。

来自API:ConcurrentModificationException

  

当不允许进行此类修改时,检测到并发修改对象的方法可能抛出此异常。

     

例如,一个线程通常不允许在另一个线程迭代它时修改Collection

你的代码很乱,因此很难弄清楚发生了什么,但我会检查:

  • 共享参考
  • 所有remove AND add

答案 1 :(得分:3)

我认为只需查找ConcurrentModificationException的javadoc即可回答您的问题。你试过吗?

Iterator.remove()导致异常,可能是在linke k.remove()上。这意味着您修改了迭代时迭代的List,这是不允许的。所以你需要找出c.getDataPoints()正在发生变化的地方。我猜这是因为你最终找到了一个集群d,分配给tempCluster,然后更改了它的数据点(最终是你正在迭代的列表。

答案 2 :(得分:0)

如果您需要从列表中删除少量元素。您可以维护另一个列表,例如要删除的元素。最后调用removeAll(collection)。当然,这对于大量数据来说并不好。

答案 3 :(得分:0)

请记住一些事项以避免并发访问问题:

首先,方法(startAnalysis)是一个实例方法。因此,同步将特定于其实例。因此,您需要确保尝试访问此方法的所有线程必须使用相同的实例来避免并发访问问题。如果每个线程都引用不同的实例,那么将允许所有线程执行该方法,最终可能导致并发问题。

其次,应该总是更喜欢使用Iterator而不是for:每个循环来迭代集合,以避免并发访问/修改问题。

此外,您可以使用concurrent collection api类来避免并发问题。这些类在这些要求中被大量使用,以避免并发修改问题。

希望这有帮助。