ConcurrentModificationException issue when starting two threads

So, I am currently working on a server that supports multie clients, I have one thread that checks if any sockets are connected to a given port and then adds them to an arraylist that uses another thread to update everything. what do i need to do with the client (update information, check DataInputStream, send text through server), etc.

Client code:

public class Loop implements Runnable{

ArrayList<ClientInstance> clientsConnected = new ArrayList<ClientInstance>();

@Override
public void run() {
    while(true) {
        checkInputStream();
    }

}

public void checkInputStream() {
    for (ClientInstance s : clientsConnected) {
        s.checkInputStream();
    }
}

      

Server code:

public synchronized void waitForClient() {
    try {
        System.out.println("Waiting for client on port: "
                + serverSocket.getLocalPort());
        Socket client = serverSocket.accept();
        System.out.println("Client Connected! " + client.getInetAddress());
        loop.getClientsConnected().add(new ClientInstance(client));
        System.out.println("Client added to clients connected! ");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

      

But when I start the server and then connect one client to it, it works fine, but when I connect another, it gives me this problem:

Exception in thread "Thread-1" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)

      

What should I do?

+3


source to share


3 answers


This is because you are modifying the arraylist (i.e. adding the item to the list in the method waitForClient()

) and at the same time iterating over it in the method checkInputStream()

.



As @Arjit mentioned, use CopyOnWriteArrayList

instead ArrayList

.

+1


source


Use CopyOnWriteArrayList

to fix it

List<String> myList = new CopyOnWriteArrayList<String>();     
myList.add("1");
myList.add("2");
myList.add("3");myList.add("4");myList.add("5");
System.out.println("List Value:"+value);

        Iterator<String> it = myList.iterator();
        while(it.hasNext()){
            String value = it.next();                    

            if(value.equals("3")){
                myList.remove("4");
                myList.add("6");
                myList.add("7");
            }
        }
        System.out.println("List Size:"+myList.size());

      

Output: -



List Value:1
List Value:2
List Value:3
List Value:4
List Value:5
List Size:6

      

PS: -

  • Concurrent collection classes can be modified by avoiding ConcurrentModificationException

    .

  • In the case CopyOnWriteArrayList

    , the iterator does not fit the changes into the list and does not work in the original list.

+1


source


Although you are synchronized for the method waitForClient

(this is where you insert the elements), you are not blocking for the method checkInputStream

.

You can use CopyOnWriteArrayList

instead ArrayList

. He already answered in the question "Avoid possible concurrency problem when returning LIST"

0


source







All Articles