title: java.util.AbstractList$Itr.checkForComodification Triple Events
body: <p>I run a server and it has an event handler that handles a timing system
  When I run 3 of them in a row, it gives this exception</p>
  
  <pre><code>Exception in thread "Thread-8" java.util.ConcurrentModificationException
          at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
          at java.util.AbstractList$Itr.next(AbstractList.java:343)
          at EventManager.run(EventManager.java:77)
          at java.lang.Thread.run(Thread.java:662)
  </code></pre>
  
  <p>here's the method that the issue is coming from:</p>
  
  <pre><code>EventManager.getSingleton().addEvent( new Event() { 
                  public void execute(EventContainer c) {
                      p.createProjectile(p.absY, p.absX, offsetY, offsetX, 1166, 43, 31, 70, p2.playerId);
                      c.stop(); // stops the event from running
                  }
              }, 950); // in ms (1 second = 1000 ms)
  EventManager.getSingleton().addEvent( new Event() { 
                  public void execute(EventContainer c) {
                      p2.applyDAMAGE(misc.random(25));
                      c.stop(); // stops the event from running
                  }
              }, 1300); // in ms (1 second = 1000 ms)
              p.secondsTillNextDfsSpecial = 120;
  EventManager.getSingleton().addEvent( new Event() { 
                  public void execute(EventContainer c) {
                      p.secondsTillNextDfsSpecial--;
                      if (p.secondsTillNextDfsSpecial == 0) {
                          p.canPerformDfsSpecial = true;
                          c.stop(); // stops the event from running
                      }
                  }
              }, 1000); // in ms (1 second = 1000 ms)
  </code></pre>
  
  <p><br></p>
  
  <pre><code>import java.util.ArrayList;
  import java.util.List;
  
  /**
   * Manages events which will be run in the future.
   * Has its own thread since some events may need to be ran faster than the cycle time
   * in the main thread.
   * 
   * @author Graham
   *
   */
  public class EventManager implements Runnable {
  
  
  /**
   * A reference to the singleton;
   */
  private static EventManager singleton = null;
  
  /**
   * A list of events that are being executed.
   */
  private List&lt;EventContainer&gt; events;
  
  /**
   * Initialise the event manager.
   */
  private EventManager() {
      events = new ArrayList&lt;EventContainer&gt;();
  }
  
  /**
   * The event manager thread. So we can interrupt it and end it nicely on shutdown.
   */
  private Thread thread;
  
  /**
   * Gets the event manager singleton. If there is no singleton, the singleton is created.
   * @return The event manager singleton.
   */
  public static EventManager getSingleton() {
      if(singleton == null) {
          singleton = new EventManager();
          singleton.thread = new Thread(singleton);
          singleton.thread.start();
      }
      return singleton;
  }
  
  /**
   * Initialises the event manager (if it needs to be).
   */
  public static void initialise() {
      getSingleton();
  }
  
  /**
   * The waitFor variable is multiplied by this before the call to wait() is made.
   * We do this because other events may be executed after waitFor is set (and take time).
   * We may need to modify this depending on event count? Some proper tests need to be done.
   */
  private static final double WAIT_FOR_FACTOR = 0.5;
  
  @Override
  /**
   * Processes events. Works kinda like newer versions of cron.
   */
  public synchronized void run() {
      long waitFor = -1;
      List&lt;EventContainer&gt; remove = new ArrayList&lt;EventContainer&gt;();
  
      while(true) {
  
          // reset wait time
          waitFor = -1;
  
          // process all events
          for(EventContainer container : events) {
              if(container.isRunning()) {
                  if((System.currentTimeMillis() - container.getLastRun()) &gt;= container.getTick()) {
                      container.execute();
                  }
                  if(container.getTick() &lt; waitFor || waitFor == -1) {
                      waitFor = container.getTick();
                  }
              } else {
                  // add to remove list
                  remove.add(container);
              }
          }
  
          // remove events that have completed
          for(EventContainer container : remove) {
              events.remove(container);
          }
          remove.clear();
  
          // no events running
          try {
              if(waitFor == -1) {
                  wait(); // wait with no timeout
              } else {
                  // an event is running, wait for that time or until a new event is added
                  int decimalWaitFor = (int)(Math.ceil(waitFor*WAIT_FOR_FACTOR));
                  wait(decimalWaitFor);
              }
          } catch(InterruptedException e) {
              break; // stop running
          }
      }
  }
  
  /**
   * Adds an event.
   * @param event The event to add.
   * @param tick The tick time.
   */
  public synchronized void addEvent(Event event, int tick) {
      events.add(new EventContainer(event,tick));
      notify();
  }
  
  /**
   * Shuts the event manager down.
   */
  public void shutdown() {
      this.thread.interrupt();
  }
  
  }&lt;/code&gt;&lt;/pre&gt;
  </code></pre>