【问题标题】:ConcurrentModificationException Issue When Running Two Thread运行两个线程时出现 ConcurrentModificationException 问题
【发布时间】:2015-06-04 04:21:23
【问题描述】:

所以,我目前正在开发一个支持多客户端的服务器,我有一个线程检查是否有任何套接字连接到给定端口,然后将它们添加到另一个线程用来更新我的所有内容的数组列表中需要与客户端做(更新信息,检查数据输入流,通过服务器发送文本)等等。

客户代码:

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)

我该怎么办?

【问题讨论】:

    标签: java multithreading arraylist concurrency network-programming


    【解决方案1】:

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

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

    【讨论】:

    • 我将如何解决这个问题?我试过让这两种方法同步,但这没有帮助。
    • 在方法 checkInputStream 中创建一个新的 Collections.unmodifiableList。
    • 或使用 CopyOnWriteArrayList - 可以修改并发集合类以避免 ConcurrentModificationException。
    • @Naman - 迭代器将不起作用 - 因为它只允许删除方法,但如果您向其中添加元素,它将抛出 ConcurrentModificationException。
    • 哦,我明白了。谢谢告知。将更新代码。
    【解决方案2】:

    使用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 的情况下,迭代器不适应列表中的更改并在原始列表上工作。

    【讨论】:

      【解决方案3】:

      虽然您为方法 waitForClient 进行了同步(您在此处插入元素),但您并没有为方法 checkInputStream 进行锁定。

      您可以使用CopyOnWriteArrayList 代替ArrayList。问题"Avoiding a possible concurrency issue with a LIST being returned"已经回答了

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-19
        • 1970-01-01
        • 1970-01-01
        • 2021-06-29
        相关资源
        最近更新 更多