运行 两个线程时的 ConcurrentModificationException 问题

ConcurrentModificationException Issue When Running Two Thread

所以,我目前正在一个支持多客户端的服务器上工作,我有一个线程检查是否有任何套接字连接到给定端口,然后将它们添加到另一个线程用来更新的数组列表中我需要对客户端执行的所有操作(更新信息、检查 DataInputStream、通过服务器发送文本)等等。

客户代码:

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();
    }
}

服务器代码:

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();
    }
}

但是当我 运行 服务器然后将一个客户端连接到它时它工作正常,但是当我连接另一个客户端时它给了我这个问题:

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

我该怎么办?

这是因为您正在修改 arraylist(即在 waitForClient() 方法中添加列表中的元素),同时您在 checkInputStream() 方法中对其进行迭代。

如@Arjit 所述,使用 CopyOnWriteArrayList 而不是 ArrayList

尽管您为方法 waitForClient 进行了同步(您在此处插入元素),但您没有为方法 checkInputStream.

锁定

您可以使用 CopyOnWriteArrayList 而不是 ArrayList。已经在问题 "Avoiding a possible concurrency issue with a LIST being returned"

中回答了

使用CopyOnWriteArrayList修复

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());

输出:-

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

PS:-

  1. 并发集合类可以修改避免ConcurrentModificationException.

  2. CopyOnWriteArrayList 的情况下,迭代器不适应列表中的更改并在原始列表上工作。