2012-02-10 40 views
2

我正在寫一個有許多圈子在屏幕上移動的小遊戲。
我在管理兩個線程圓如下:
解決ConcurrentModificationException

public void run() { 
    int stepCount = 0; 
    int dx; 
    int dy; 
    while (m_threadTrap){ 
     dx = 0; 
     dy = 0; 

     synchronized (m_circles) { 
      for (Iterator<Circle> it = m_circles.iterator(); it.hasNext();){ 
       Circle c = it.next(); //Exception thrown here. 
       if (c.getDirX() != 0) 
        if (stepCount % c.getDirX() == 0){ 
         dx = 1; 
        } 
       if (c.getDirY() != 0) 
        if (stepCount % c.getDirY() == 0){ 
         dy = 1;     
        } 

       c.move(dx, dy); 
      } 
     } 
     if (stepCount == 150000){ 
      stepCount = 0; 
     } 
     stepCount++; 
    } 
} 

m_circles在圓的ArrayList。

而以下主題:

public void run() { 
    while (m_threadTrap){ 
     int topPosition; 
     int bottomPosition; 
     int leftPosition; 
     int rightPosition; 
     ArrayList<Circle> removedCircles = new ArrayList<Circle>(); 
     synchronized (m_circles.getCircles()) { 
      for (Iterator<Circle> it = m_circles.getCircles().iterator(); it.hasNext();){ 
       Circle c = it.next(); 

       // Some calculation to evaluate which circles should be removed 
        removedCircles.add(c); 
       } 
      } 
     } 
     try{ 
      Thread.sleep(25); 
     } 
     catch (Exception e) { } 

     m_circles.getCircles().removeAll(removedCircles); 

     if (m_circles.getCircles().size() < 30) 
      m_circles.addNewCircle(); 

     repaint(); 
    } 
} 

我的問題是,我在第一線的線

Circle c = it.next(); 

得到ConcurrentModificationException的。起初我試着用foreach循環來檢查ArrayList,這給了我同樣的例外。
在研究了這個例外之後,我看到了兩個解決方案:
1.將訪問集合的部分放入同步塊中。
2.使用集合的Iterator對象。
他們都沒有爲我解決它。

回答

1

對於synchronized() {}塊有效,對受保護對象的所有訪問必須包裝在同步塊中。你可能忘了包裝一些訪問。

另一個「疑難雜症」的是,ConcurrentModificationException的也可以意味着它是在同一個線程同時修改。例如,如果您在遍歷集合中移除某個元素時,可能會得到此異常。 (作爲例外,您可以通過迭代器本身安全地移除元素)

+0

非常感謝你,確實有兩個線程是我忘記包裝的另一個接入點。 – Nadavrbn 2012-02-10 08:44:06

1

ConcurrentModificationException表示您正在遍歷集合,並且在迭代時某人(當前線程或另一個線程)修改底層集合而不使用Iterator.remove()。無論何時調用Iterator上的操作,它都會檢查基礎集合是否未更改。使用foreach不會改變一件事情,因爲它使用迭代器來執行循環。

您的解決方案是:

  1. 創建一個新的集合:

    爲(圓C:新的ArrayList(m_circles.getCircles())迭代器()){// 一些計算評估哪些圈子應該被刪除 removedCircles.add(c); }

  2. 或同步同一個對象(可以同步不同的對象,因此它不會做任何事情)每當你正在修改或訪問該集合

相關問題