optorsim создает исключение ConcurrentModificationException

1

эта программа (optoesim) бросает java.util.ConcurrentModificationException в строке для stats.put("jobTimesWithQueue", new LinkedHashMap(_jobTimesWithQueue)); ,

Это программа с открытым исходным кодом, и я ничего не изменил. Может кто-нибудь, пожалуйста, объясните мне, что это значит, что вызывает его, и как я могу его избежать.

Exception in thread ConcurrentModificationException

java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:711)** 
at java.util.LinkedHashMap$LinkedEntryIterator.next(LinkedHashMap.java:744)

at java.util.LinkedHashMap$LinkedEntryIterator.next(LinkedHashMap.java:742)
at java.util.HashMap.putMapEntries(HashMap.java:511)
at java.util.LinkedHashMap.<init>(LinkedHashMap.java:384)
at org.edg.data.replication.optorsim.SimpleComputingElement.getStatistics(SimpleComputingElement.java:164)
at org.edg.data.replication.optorsim.GridDataThread.run(GridDataThread.java:95)


public Statistics getStatistics() {
    Map stats = new HashMap();
      // After remove see the result here.
    OptorSimParameters params = OptorSimParameters.getInstance();
    float _usage = _time.getTimeMillis() - _startRunning == 0 ? 0 : 100 *_workingTime/(_time.getTimeMillis() - _startRunning);
    stats.put("usage",  new Float(_usage));
    stats.put("remoteReads",  new Long(_remoteReads));
    stats.put("localReads",  new Long(_localReads));
    if( params.outputStatistics() ==3) {

        stats.put("jobTimes",  new LinkedHashMap( _jobTimes));
        stats.put("jobTimesWithQueue", new LinkedHashMap(_jobTimesWithQueue));
        stats.put("jobFiles",  new LinkedHashMap(_jobFiles));
        stats.put("numberOfJobs", new Integer(_jobsCompleted));
        stats.put("workerNodes",  new Integer(_workerNodes));
        stats.put("status",  new Boolean(_active));
        stats.put("queueLength",  new Integer(_inputJobHandler.getQueueSize()));
        stats.put("runnableStatus",  new Boolean(_runnable));
    }
    stats.put("totalJobTime",  new Float(_totalJobTime/(float)1000));


    long meanJobTime = 0;
    if (_jobsCompleted!=0)
       meanJobTime = _workingTime/_jobsCompleted;
      /////////////////////////////////////////
    stats.put("meanJobTime",  new Long(meanJobTime));

    return new Statistics(this, stats);
}
**Edit:**

Я хотел бы показать вам все детали erreur

Exception in thread "Thread-72" java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:711)
at java.util.LinkedHashMap$LinkedEntryIterator.next(LinkedHashMap.java:744)
at java.util.LinkedHashMap$LinkedEntryIterator.next(LinkedHashMap.java:742)
at java.util.HashMap.putMapEntries(HashMap.java:511)
at java.util.LinkedHashMap.<init>(LinkedHashMap.java:384)
at org.edg.data.replication.optorsim.SimpleComputingElement.getStatistics(SimpleComputingElement.java:174)
at org.edg.data.replication.optorsim.SiteDataThread.run(SiteDataThread.java:112)

когда я нажимаю на first linkedhashMap

    final LinkedHashMap.Entry<K,V> nextNode() {
        LinkedHashMap.Entry<K,V> e = next;
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
        if (e == null)
            throw new NoSuchElementException();
        current = e;
        next = e.after;
        return e;
    }

вторая связанная карта

 final class LinkedEntryIterator extends LinkedHashIterator
    implements Iterator<Map.Entry<K,V>> {
    public final Map.Entry<K,V> next() { return nextNode(); }
}

и erreur находится в 3-й строке. 3-ий связанныйhashMap

final class LinkedEntryIterator extends LinkedHashIterator
    implements Iterator<Map.Entry<K,V>> {
    public final Map.Entry<K,V> next() { return nextNode(); }
}

erreur находится в первой строке hashmap

  for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
            K key = e.getKey();
            V value = e.getValue();
            putVal(hash(key), key, value, false, evict);

LinkedHashMap

 public LinkedHashMap(Map<? extends K, ? extends V> m) {
    super();
    accessOrder = false;
    putMapEntries(m, false);
}

erreur находится в линии

     putMapEntries(m, false);
at org.edg.data.replication.optorsim.SimpleComputingElement.getStatistics(SimpleComputingElement.java:174)

это все код simpleComputing Elelement

package org.edg.data.replication.optorsim;

/ * В ComputingElement выполняется поток, который выполняет GridJobs *, заданный ему через {@link JobHandler}. Для каждого требуемого файла * ComputingElement вызывает getBestFile(), который возвращает * местоположение лучшей реплики файла в соответствии с * выбранным алгоритмом оптимизации, который мог или не мог выполнить репликацию *. ComputingElement считывает файл из этого места * и обрабатывает его. Время обработки файла рассчитывается как * время, указанное в файле параметров, деленное на количество рабочих * узлов в ComputingElement. *

* Каждый ComputingElement может выполнять только одно задание за раз. * Информация о времени, затраченном на каждое задание, может быть найдена в выводе статистики * в конце моделирования, если в файле параметров выбран файл статистики 3 * или из гистограмм задания времени *, если используется графический интерфейс. *

* Авторское право (c) 2002 CERN, ITC-first, PPARC, от имени EU DataGrid. * Для условий лицензии см. Файл LICENSE или * http://www.edg.org/license.html *

* @since JDK1.4/*

public class SimpleComputingElement implements ComputingElement {

private static int _LastCEId = 0;

private GridSite _site; 
private String _ceName;  
private boolean _imAlive;
private boolean _paused = false;
private int _CEId;
private long _workingTime = 0;
private long _startRunning;
private long _totalJobTime = 0;
private Map _jobTimes = new LinkedHashMap();
private Map _jobTimesWithQueue = new LinkedHashMap();
private Map _jobFiles = new LinkedHashMap();

private int _jobsCompleted = 0;

protected JobHandler _inputJobHandler;
protected boolean _runnable = false;
protected boolean _active=false;
protected long _remoteReads = 0;
protected long _localReads = 0;
protected int _workerNodes = 0;
protected float _workerCapacity = 0;
protected GridTime _time;

public SimpleComputingElement( GridSite site,  int workerNodes, float capacity) {

    OptorSimParameters params = OptorSimParameters.getInstance();

    _time = GridTimeFactory.getGridTime();
    _site = site;
    _workerNodes = workerNodes;
    _workerCapacity = capacity;
    _CEId = ++_LastCEId;
    _ceName = "CE"+_CEId+"@"+_site;
    _inputJobHandler = new JobHandler( params.getMaxQueueSize());
    _imAlive = true;
    _site.registerCE( this);
    _startRunning = _time.getTimeMillis();
}

/**
 * Return a more meaningful name.
 * @return the CE name
 */
public String toString() {
    return _ceName;
}

/**
 * Check whether this CE is active (processing jobs) or idle.
 */
public boolean active() {
    return _active;
}

/**
 * Check whether this CE is still running or has been shut down.
 */
public boolean imAlive() {
      return _imAlive;
}

/**
 * A method to return the input sandbox for this computing element.
 */
public JobHandler getJobHandler() {
    return _inputJobHandler;
}

/**
 * Method to get the site that this CE is on.
 * @return The site this CE is on.
 */
public GridSite getSite() {
    return _site;
}


/**
 * Method to give the name of this CE.
 * @return The name of this CE.
 */
public String getCeName() {
    return _ceName;
}

public int getWorkerNodes() {
    return _workerNodes;
}

/**
 * Method to check against our ID 
 */
public boolean iAm( int id) {
    return _CEId == id;
}

/**
 * Method to collate and return information relevant 
 * to this CE as a {@link Statistics} object.
 * @return The statistics of this CE
 */



public Statistics getStatistics() {
    Map stats = new HashMap();




    OptorSimParameters params = OptorSimParameters.getInstance();
    float _usage = _time.getTimeMillis() - _startRunning == 0 ? 0 : 100 *_workingTime/(_time.getTimeMillis() - _startRunning);
    stats.put("usage",  new Float(_usage));
    stats.put("remoteReads",  new Long(_remoteReads));
    stats.put("localReads",  new Long(_localReads));
    if( params.outputStatistics() ==3) {
                    /*  LinkedHashSet<String> lhs = new LinkedHashSet<String>();




        stats.put("jobTimes",  new LinkedHashMap( _jobTimes));
        stats.put("jobTimesWithQueue", new LinkedHashMap(_jobTimesWithQueue));
        stats.put("jobFiles",  new LinkedHashMap(_jobFiles));


        stats.put("numberOfJobs", new Integer(_jobsCompleted));
        stats.put("workerNodes",  new Integer(_workerNodes));
        stats.put("status",  new Boolean(_active));
        stats.put("queueLength",  new Integer(_inputJobHandler.getQueueSize()));
        stats.put("runnableStatus",  new Boolean(_runnable));
    }
    stats.put("totalJobTime",  new Float(_totalJobTime/(float)1000));


    long meanJobTime = 0;
    if (_jobsCompleted!=0)
       meanJobTime = _workingTime/_jobsCompleted;
      /////////////////////////////////////////
    stats.put("meanJobTime",  new Long(meanJobTime));

    return new Statistics(this, stats);
}

/**
 * When running, the ComputingElement processes all the jobs
 * submitted to it through the JobHandler, sleeping while the
 * JobHandler is empty. It is notified to shut down by the 
 * ResourceBroker.
 */
public void run() {

    // Boost our priority
    Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
    Double execTime;
    OptorSimParameters params = OptorSimParameters.getInstance();

    _runnable = true;

    // to keep thread running
    for( GridJob job=null; job != null || _imAlive; ) {

        _active=false;
        job=_inputJobHandler.get();  // This potentially blocks

        // We might get a null job from JobHandler, if so, skip any further activity
        if( job == null)
        continue;

        job.started();

        OptorSimOut.println(_ceName+"> starting to process "+job+" (queue length now "+
                   _inputJobHandler.getQueueSize()+")");
        _active=true;       

        // Install our optimiser
        Optimisable replicaOptimiser = OptimiserFactory.getOptimisable( _site);

        AccessPatternGenerator accessPatternGenerator 
        = AccessPatternGeneratorFactory.getAPGenerator(job);

        String[] logicalfilenames = new String[1];

        List filesAccessed  = new LinkedList();     

        for( String lfn = accessPatternGenerator.getNextFile();
         lfn != null; 
         lfn = accessPatternGenerator.getNextFile()) {

            filesAccessed.add(lfn);

            // Pack the logical file name into the expected structure:      
            logicalfilenames[0] = lfn;
            float[] fileFractions = new float[1];
            fileFractions[0] = (float)1.0;

                // Use optimiser to locate best replica of this file
            DataFile[] files = replicaOptimiser.getBestFile(logicalfilenames, 
                                            fileFractions);
            if( files.length != 1) {
                System.out.println( "ASSERT FAILED: CE, getBestFile return array with wrong number of entries: "+  files.length  +" != 1");
                continue; // skip to next file
            }

            if(files[0] == null) {
                System.out.println( _ceName + "> ERROR getBestFile returned"+
                    " null for "+logicalfilenames[0]);
                continue; // skip to next file
            }

            StorageElement fileSE = files[0].se();
            GridSite fileSite = fileSE.getGridSite();

            // Special case.  If file is remote, then simulate the remoteIO, unPin and move on to next file.
            if( _site != fileSite) {
                simulateRemoteIO( files[0], fileFractions[0]);

                // log this as an access on the close SE (if it exists!)
                if(_site.hasSEs())
                    _site.getCloseSE().accessFile(files[0]);

                if(_workerNodes != 0) {
                    execTime = new Double((job.getLatency() + job.getLinearFactor()*files[0].size())/(_workerNodes*_workerCapacity));
                    _time.gtSleep(execTime.longValue());
                }
                files[0].releasePin();
                _remoteReads++;
                continue;
            }
            else {
                fileSE.accessFile(files[0]);
                _localReads++;
            }

            // process the file
            if(_workerNodes != 0) {
                execTime = new Double((job.getLatency() + job.getLinearFactor()*files[0].size())/(_workerNodes*_workerCapacity));
//              System.out.println(this.toString()+"> processing file...");
                _time.gtSleep(execTime.longValue());
            }

            files[0].releasePin();

            //A while loop the ce enters when paused by gui
            while(_paused){
                _time.gtWait(this);
            }

        } // for each datafile in job

        // statistics logging
        long duration = _time.getTimeMillis() - job.timeStarted();
        long durationWithQueue = _time.getTimeMillis() - job.timeScheduled();
        if( duration < 0) {
            OptorSimOut.println("BUG> Duration < 0!!");
        }
        _totalJobTime += durationWithQueue;
        _workingTime += duration;
        _jobsCompleted++;


        if( params.outputStatistics() == 3 || params.useGui()) {
            _jobTimes.put(job.toString(), new Long(duration));
            _jobTimesWithQueue.put(job.toString(), new Long(durationWithQueue));
            _jobFiles.put( job.toString(), filesAccessed);
        }

    } // while there are jobs left to run        
    _runnable = false;
} // run


/**
 * A routine used by the CE to simulate remote IO. The GridContainer copy() method is
 * used to block the equivalent amount of time.
 */
protected void simulateRemoteIO( DataFile remoteFile, float fraction) 
{
    GridContainer gc = GridContainer.getInstance();
    gc.copy( remoteFile, _site, fraction);
}


/**
 * GUI calls this method to pause the ComputingElement
 * threads when pause button is pressed.
 */
public void pauseCE() {
    _paused = true;
}

/**
 * GUI calls this method to unpause the ComputingElement
 * threads when continue button is pressed.
 */
public void unpauseCE() {
    _paused = false;
    _time.gtNotify(this);
}

/**
 * The ResourceBroker calls this method when it has
 * distributed all the jobs to shut down the ComputingElement
 * threads.
 */
public void shutDownCE(){
    _imAlive = false;
}

}

at org.edg.data.replication.optorsim.SiteDataThread.run(SiteDataThread.java:112)

erreur находится в линии

 st = ce.getStatistics();






{
              //get the statistics object for this comp. element
              ce = site.getCE();
              st = ce.getStatistics();

              //sample mean job time
              Object r1 = st.getStatistic("meanJobTime");
              String stat1 = r1.toString();
              int stat1Int = Integer.parseInt(stat1);
              seriesSMJTVTime.add(timeSecs, stat1Int);

              //sample job times
              Object r2 = st.getStatistic("jobTimes");
              Map m = (Map)r2;
              int pairs = m.size();
              //if (number of previous key-value pairs != pairs)
              //    instantiate new histarray and fill with job time values
              if (prevNoOfPairs!=pairs)
              {
                 histarray = new double[pairs];
                 int i=0;
                 prevNoOfPairs++;
                 Set keySet = m.keySet();
                 Iterator iter = keySet.iterator();
                 while (iter.hasNext())
                 {
                    Object key = iter.next();
                    Object value = m.get(key);
                    String duration = value.toString();
                    float jobTime = Float.parseFloat(duration);
                    histarray[i] = jobTime;
                    i++;
                 }
              }

              //sample usage
              Object r3 = st.getStatistic("usage");
              String stat3 = r3.toString();
              float coUsage = Float.parseFloat(stat3);
              /* if (range values identical for last three readings)
               *    remove intermediate statistic
               */
              if (coUsage==prevCoUsage&&coUsage==prevPrevCoUsage)
              {
                 int itemCount = seriesSSEUVTime.getItemCount();
                 if (itemCount>2)
                    seriesSSEUVTime.remove(itemCount-1);
              }
              prevPrevCoUsage = prevCoUsage;
              prevCoUsage = coUsage;
              seriesSCEUVTime.add(timeSecs, coUsage);
           }
        }
  • 0
    Является ли jobTimes полем? (Это не объявлено в методе.) Если это так, и другой поток модифицирует его, то это может быть причиной. Я не могу сказать, из какой информации предоставлено здесь, хотя.
  • 0
    Я не знаю, но это карта статистики, когда я запускаю программу [remoteReads = 0, queueLength = 200, runnableStatus = true, localReads = 32, jobTimes = {jpsijob_16 = 890085, incmuonjob_24 = 712508}, jobTimesWithQueue = {jpsijob_16 = 89 , .................
Показать ещё 1 комментарий
Теги:
concurrency
concurrentmodification

1 ответ

0

ConcurrentModificationException говорит, что кто-то изменил элемент, который не является текущим потоком во время текущего потока, используемого в itme..

Таким образом, некоторые другие потоки могут проходить через карту. Это, вероятно, один объект или одноэлементный объект из-за этой строки: OptorSimParameters.getInstance(); который использовался в общем случае с дизайнером Singelton.

Таким образом, это означает, что один и тот же объект изменился с 2-х мест. Из кода, который вы показали, и другой части кода.

Если это с открытым исходным кодом, возможно, что это никогда не срабатывало. Или это ошибка, которую вы обнаружили. На самом деле у вас нет, что с этим делать, кроме, может быть, найти, кто вызывает OptorSimParameters.getInstance(); и попытайтесь понять, кто еще это называется, и изменить или использовать эту карту

Надеюсь, что это имеет смысл

РЕДАКТИРОВАТЬ:

Это исключение случается, когда кто-то вроде этого случается

Iterator<Point> iter = points.iterator();
while (iter.hasNext()) {
Point p = iter.next();

//Antoher loop inside this one that will just iterate the itmes
Iterator<Point> iter2 = points.iterator();
while (iter2.hasNext()) {
    Point p = iter2.next();
    if (p.equals(pointWeWantToRemove)) {
        iter2.remove();
    }
}

iter.remove();

В этом случае выше выполняется цикл внутри цикла. Какой внешний цикл удаляет элементы один за другим, а внутренний удаляет определенную Точку. points.iterator() будет вызываться в этом случае, потому что итераторы работают в одном списке и удаляют элементы друг для друга. После создания итератора points.iterator() он сохранит размер инициализации коллекции и после этого он проверит его:

if (initSize != collection.size()) { 
     throw new ConcurrentModificationException ();
}

Поэтому, если вы создали как-то 2 итератора, которые меняют одну и ту же коллекцию, в то же время это произойдет... Вы показали одну часть кода, но если вы можете найти другой итератор, нам нужно подумать, как избежать этой вещи. Если другой метод, который использовал коллекцию только для чтения, вы можете создать клон перед его чтением, а также перебирать клон из коллекции, и он решит вашу проблему

Надеюсь, что это имеет смысл

  • 0
    но что я могу добавить, чтобы избежать этого исключения и где? Я думаю, что исключение в статистике карты.
  • 0
    Вы можете попробовать поставить синхронизацию на сигнатуру метода. Вы можете попробовать. Я точно не уверен .. Можете ли вы добавить еще одну часть кода, которая использует эту карту? Если вы используете банку или банку стороннего производителя, вы ничего не можете сделать. За исключением смены классов, но я бы не советовал это делать.
Показать ещё 8 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню