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?
source to share
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
.
source to share
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.
source to share
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"
source to share