Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 7 of 7

Thread: Best way to solve this ConcurrentModificationException

  1. #1
    Member
    Join Date
    Jul 2013
    Location
    Europe
    Posts
    378
    Thanks
    0
    Thanked 64 Times in 54 Posts

    Default Best way to solve this ConcurrentModificationException

    Hi.

    I have a problem with a concurrent modification exception in a listener-based application. It comes from removing a listener while the listener is active.
    Here is a simple example program:
    public class YouCantStopTheSignal {
     
    	public static void main(String[] args) {
    		SignalEmitter se = new SignalEmitter();
    		new SignalUser(se);
    		se.sendSignal("A");
    		se.sendSignal("B");
    		se.sendSignal("C");
    		se.sendSignal("disconnect"); // boom! -> ConcurrentModificationException
    		se.sendSignal("D");
    		sg.sendSignal("E");
    	}
     
    }
    public class SignalEmitter {
     
    	private final List<SignalListener> listeners;
     
    	public SignalEmitter() {
    		listeners = new ArrayList<>();
    	}
     
    	public void addListener(SignalListener l) {
    		listeners.add(l);
    	}
     
    	public void removeListener(SignalListener l) {
    		listeners.remove(l);
    	}
     
    	protected void sendSignal(String signal) {
    		for (SignalListener l : listeners) {
    			l.send(signal);
    		}
    	}
     
    }
    public class SignalUser implements SignalListener {
     
    	private final SignalEmitter signalEmitter;
     
    	public SignalUser(SignalEmitter se) {
    		signalEmitter = se;
    		signalEmitter.addListener(this);
    	}
     
    	public void send(String signal) {
    		if (signal.equals("disconnect")) {
    			signalEmitter.removeListener(this); // boom! -> ConcurrentModificationException
    		} else {
    			// doStuff
    			System.out.println("In: "+signal);
    		}
    	}
     
    }


    I have 2 solutions in mind, but I dont like either of those.

    Solution 1:
    I add an additional List<SignalListener> to my SignalEmitter. This list will hold SignalListeners that are supposed to be removed:
    Changes:
    public class SignalEmitter {
     
    	private final List<SignalListener> listeners;
    	private final List<SignalListener> toBeRemoved;
     
    	public SignalEmitter() {
    		listeners = new ArrayList<>();
    		toBeRemoved = new ArrayList<>();
    	}
     
    	public void addListener(SignalListener l) {
    		listeners.add(l);
    	}
     
    	public void removeListener(SignalListener l) {
    		toBeRemoved.add(l);
    	}
     
    	protected void sendSignal(String signal) {
    		for (SignalListener l : listeners) {
    			l.send(signal);
    		}
    		listeners.removeAll(toBeRemoved);
    		toBeRemoved.clear();
    	}
     
    }
    I dont like this solution because it appears to me to be a little bit of overkill for this rather simple task.


    Solution 2:
    I add another method to my SignalListener. This method will tell the SignalEmitter whether the listener is still interested or not.
    Changes:
    public class SignalEmitter {
     
    	private final List<SignalListener> listeners;
     
    	public SignalEmitter() {
    		listeners = new ArrayList<>();
    	}
     
    	public void addListener(SignalListener l) {
    		listeners.add(l);
    	}
     
    	protected void sendSignal(String signal) {
    		Iterator<SignalListener> iterator = listeners.iterator();
    		while (iterator.hasNext()) {
    			SignalListener l = iterator.next();
    			l.send(signal);
    			if (l.notInterestedAnymore()) {
    				iterator.remove();
    			}
    		}
    	}
     
    }
    public class SignalUser implements SignalListener {
     
    	private boolean notInterestedAnymore;
     
    	public SignalUser(SignalEmitter se) {
    		se.addListener(this);
    		notInterestedAnymore = false;
    	}
     
    	public void send(String signal) {
    		if (signal.equals("disconnect")) {
    			notInterestedAnymore = true;
    		} else {
    			// doStuff
    			System.out.println("In: "+signal);
    		}
    	}
     
    	public boolean notInterestedAnymore() {
    		return notInterestedAnymore;
    	}
     
    }
    I dont like this solution either, mainly because it is clunky and verbose. Also: in my opinion it should not be an attribute of the listener whether it is listening or not.




    What do you think? What should I do?
    Is there a better way?

    Thanks in advance.


  2. #2
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    SW Missouri
    Posts
    20,067
    Thanks
    47
    Thanked 2,146 Times in 2,119 Posts

    Default Re: Best way to solve this ConcurrentModificationException

    Can you post the full error message showing the stack trace?
    If you don't understand my answer, don't ignore it, ask a question.

  3. #3
    Member
    Join Date
    Jul 2013
    Location
    Europe
    Posts
    378
    Thanks
    0
    Thanked 64 Times in 54 Posts

    Default Re: Best way to solve this ConcurrentModificationException

    Sure, if you really need it.
    Exception in thread "main" java.util.ConcurrentModificationException
    	at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    	at java.util.ArrayList$Itr.next(Unknown Source)
    	at pkg.SignalEmitter.sendSignal(SignalEmitter.java:23)
    	at pkg.YouCantStopTheSignal.main(YouCantStopTheSignal.java:14)

  4. #4
    Member
    Join Date
    Jul 2013
    Location
    Europe
    Posts
    378
    Thanks
    0
    Thanked 64 Times in 54 Posts

    Default Re: Best way to solve this ConcurrentModificationException

    Still looking for help. I would really appreciate just some opinions from experienced programmers.

  5. #5
    Super Moderator copeg's Avatar
    Join Date
    Oct 2009
    Location
    US
    Posts
    5,225
    Thanks
    176
    Thanked 817 Times in 760 Posts
    Blog Entries
    5

    Default Re: Best way to solve this ConcurrentModificationException

    How about just creating a Dummy list to loop over when you fire the listeners:

    	protected void sendSignal(String signal) {
    		List<SignalListener> temp = new ArrayList<SignalListener>(listeners);
    		for (SignalListener l : temp) {
    			l.send(signal);
    		}
    	}

  6. #6
    Forum VIP
    Join Date
    Jun 2011
    Posts
    270
    My Mood
    Bored
    Thanks
    39
    Thanked 75 Times in 63 Posts
    Blog Entries
    4

    Default Re: Best way to solve this ConcurrentModificationException

    for (SignalListener l : listeners) {
        l.send(signal);
    }

    Behind the scenes, this creates an iterator. Whilst this iterator is open the .send method is attempting to remove an item from the collection, hence the ConcurrentModificationException.

    I think solution #1 is the best (keep a list of objects to be removed), however personally I would have structured this a little closer to #2 with a boolean member variable in the SignalUser class.

  7. #7
    Junior Member
    Join Date
    Jul 2014
    Posts
    16
    Thanks
    0
    Thanked 4 Times in 3 Posts

    Default Re: Best way to solve this ConcurrentModificationException

    Maybe something like this?

    import java.util.ArrayList;
    import java.util.List;
    import java.util.ListIterator;
     
    public class SignalEmitter {
     
      private final List<SignalListener> listeners;
      private ListIterator<SignalListener> li;
     
      public SignalEmitter() {
        listeners = new ArrayList<>();
      }
     
      public void addListener(SignalListener l) {
        listeners.add(l);
      }
     
      public void removeListener(SignalListener l) {
        if (li != null) {
          while(li.previous() != l) {
            // Do nothing
          }
          li.remove();
          // Readjust the iterator if necessary
        } else
          listeners.remove(l);
      }
     
      protected void sendSignal(String signal) {
        li = listeners.listIterator();
        while (li.hasNext())
          li.next().send(signal);
        li = null;
      }
     
      public List<SignalListener> getListeners() {
        return listeners;
      }
     
    }

    It's a little less verbose than Solution 2, though I'm not sure if this accomplishes what you were going for.

Similar Threads

  1. how to solve
    By onlydeb in forum What's Wrong With My Code?
    Replies: 3
    Last Post: December 30th, 2013, 03:34 PM
  2. How to solve??
    By Mumpy Zinu in forum What's Wrong With My Code?
    Replies: 0
    Last Post: November 2nd, 2013, 10:51 AM
  3. How to solve this?
    By jellescheer in forum What's Wrong With My Code?
    Replies: 4
    Last Post: September 12th, 2012, 09:14 AM
  4. anyone can help me to solve this?
    By d3sm0nd in forum What's Wrong With My Code?
    Replies: 13
    Last Post: June 27th, 2012, 06:47 AM
  5. Please can anyone help solve this ?
    By jennyb in forum Java Theory & Questions
    Replies: 1
    Last Post: January 6th, 2012, 08:45 PM