所以,我目前正在开发一个支持多客户端的服务器,我有一个线程检查是否有任何套接字连接到给定端口,然后将它们添加到另一个线程用来更新所有内容的arraylist需要使用客户端(更新信息,检查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)
我该怎么办?
答案 0 :(得分:1)
这是因为您正在修改arraylist(即在waitForClient()
方法中添加列表中的元素),同时您正在checkInputStream()
方法中进行迭代。
如@Arjit所述,使用CopyOnWriteArrayList
代替ArrayList
。
答案 1 :(得分:1)
使用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: -
可以修改并发集合类,避免使用ConcurrentModificationException
。
如果是CopyOnWriteArrayList
,迭代器不能容纳列表中的更改并在原始列表中工作。
答案 2 :(得分:0)
虽然你为方法waitForClient
进行了同步(你在这里插入元素)但你没有锁定方法checkInputStream
。
您可以使用CopyOnWriteArrayList
代替ArrayList
。它已在问题"Avoiding a possible concurrency issue with a LIST being returned"