[英]concurrent modification on arraylist
有很多並發的 mod 異常問題,但我無法找到幫助我解決問題的答案。 如果您找到答案,請提供一個鏈接,而不是僅僅投反對票。
所以我最初在嘗試搜索數組列表並刪除元素時遇到了並發 mod 錯誤。 有一段時間,我通過創建第二個數組列表,將發現的元素添加到其中,然后在 for 循環外使用 removeAll() 來解決它。 這似乎有效,但是當我使用 for 循環從多個文件導入數據時,我再次開始收到並發修改異常,但由於某種原因間歇性地出現。 任何幫助將不勝感激。
這是有問題的具體方法(以及它調用的其他方法......):
public static void removeData(ServiceRequest r) {
readData();
ArrayList<ServiceRequest> targets = new ArrayList<ServiceRequest>();
for (ServiceRequest s : serviceQueue) {
//ConcurrentModification Exception triggered on previous line
if (
s.getClient().getSms() == r.getClient().getSms() &&
s.getTech().getName().equals(r.getTech().getName()) &&
s.getDate().equals(r.getDate())) {
JOptionPane.showMessageDialog(null, s.getClient().getSms() + "'s Service Request with " + s.getTech().getName() + " on " + s.getDate().toString() + " has been removed!");
targets.add(s);
System.out.print("targetted"); }
}
if (targets.isEmpty()) { System.out.print("*"); }
else {
System.out.print("removed");
serviceQueue.removeAll(targets);
writeData(); }
}
public static void addData(ServiceRequest r) {
readData();
removeData(r);
if (r.getClient().getStatus().equals("MEMBER") || r.getClient().getStatus().equals("ALISTER")) {
serviceQueue.add(r); }
else if (r.getClient().getStatus().equals("BANNED") || r.getClient().getStatus().equals("UNKNOWN")) {
JOptionPane.showMessageDialog(null, "New Request failed: " + r.getClient().getSms() + " is " + r.getClient().getStatus() + "!", "ERROR: " + r.getClient().getSms(), JOptionPane.WARNING_MESSAGE);
}
else {
int response = JOptionPane.showConfirmDialog(null, r.getClient().getSms() + " is " + r.getClient().getStatus() + "...", "Manually Overide?", JOptionPane.OK_CANCEL_OPTION);
if (response == JOptionPane.OK_OPTION) {
serviceQueue.add(r); }
}
writeData(); }
public static void readData() {
try {
Boolean complete = false;
FileReader reader = new FileReader(f);
ObjectInputStream in = xstream.createObjectInputStream(reader);
serviceQueue.clear();
while(complete != true) {
ServiceRequest test = (ServiceRequest)in.readObject();
if(test != null && test.getDate().isAfter(LocalDate.now().minusDays(180))) {
serviceQueue.add(test); }
else { complete = true; }
}
in.close(); }
catch (IOException | ClassNotFoundException e) { e.printStackTrace(); }
}
public static void writeData() {
if(serviceQueue.isEmpty()) { serviceQueue.add(new ServiceRequest()); }
try {
FileWriter writer = new FileWriter(f);
ObjectOutputStream out = xstream.createObjectOutputStream(writer);
for(ServiceRequest r : serviceQueue) { out.writeObject(r); }
out.writeObject(null);
out.close(); }
catch (IOException e) { e.printStackTrace(); }
}
編輯
這些更改導致並發 mod 每次觸發而不是間歇性觸發,我猜這意味着刪除代碼更好,但錯誤現在在it.remove();
處觸發it.remove();
public static void removeData(ServiceRequest r) {
readData();
for(Iterator<ServiceRequest> it = serviceQueue.iterator(); it.hasNext();) {
ServiceRequest s = it.next();
if (
s.getClient().getSms() == r.getClient().getSms() &&
s.getTech().getName().equals(r.getTech().getName()) &&
s.getDate().equals(r.getDate())) {
JOptionPane.showMessageDialog(null, s.getClient().getSms() + "'s Service Request with " + s.getTech().getName() + " on " + s.getDate().toString() + " has been removed!");
it.remove(); //Triggers here (line 195)
System.out.print("targetted"); }
}
writeData(); }
線程“AWT-EventQueue-0”中的異常 java.util.ConcurrentModificatio nException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901) at java.util.ArrayList$Itr.next(ArrayList.java:851)在 data.ServiceRequest.removeData(ServiceRequest.java:195) 在 data.ServiceRequest.addData(ServiceRequest.java:209) <...>
編輯經過更多搜索后,我已將 for 循環切換為:
Iterator<ServiceRequest> it = serviceQueue.iterator();
while(it.hasNext()) {
它又回到間歇性觸發。 我的意思是當我第一次嘗試導入數據時(removeData 方法是從 addData 方法觸發的),它會觸發並發 mod 異常,但下一次嘗試它會跳過失敗並移至另一個文件。 我知道有很多這些並發的 mod 問題,但我沒有找到任何對我的情況有幫助的東西,所以非常歡迎指向其他答案的鏈接......
這不是如何做到的,在使用迭代器遍歷 List 時刪除元素。 像那樣 :
List<ServiceRequest> targets = new ArrayList<ServiceRequest>();
for(Iterator<ServiceRequest> it = targets.iterator(); it.hasNext();) {
ServiceRequest currentServReq = it.next();
if(someCondition) {
it.remove();
}
}
如果您只有一個線程,您將不會以這種方式獲得 ConcurrentModificationException。
如果您的代碼中涉及多個線程,您可能仍會收到 ConcurrentModificationException。 解決此問題的一種方法是在您的集合 (serviceQueue) 上使用 Collections.synchronizedCollection(...),因此您將獲得一個不會產生 ConcurrentModificationException 的同步集合。 但是,您的代碼可能會變得很慢。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.