3

私はしばらくこれに固執しているので、どんな助けでも大歓迎です。

次のコードセクションがあります。

BallThread.java
@Override
public synchronized void run() {
  while (numItersCompleted < maxNumIters) {
    completedThisIter = false;
synchronized (ballList) {
    for (Ball b : ballList) { // line 35
        b.updatePosition(ballPanel.getBounds(), ballList);
    }
}
 } // other stuff


Exception in thread "Thread-2" java.util.ConcurrentModificationException
at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1091)
at java.util.ArrayList$SubList.listIterator(ArrayList.java:972)
at java.util.AbstractList.listIterator(AbstractList.java:300)
at java.util.ArrayList$SubList.iterator(ArrayList.java:968)
at Part2.BallThread.run(BallThread.java:35)

そして時々私はこれを手に入れます(BallPanelの36行目)

java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:782)
at java.util.ArrayList$Itr.next(ArrayList.java:754)
at Part2.BallPanel.paintComponent(BallPanel.java:36)
at javax.swing.JComponent.paint(JComponent.java:1029)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5138)
at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:302)
at javax.swing.RepaintManager.paint(RepaintManager.java:1188)
at javax.swing.JComponent._paintImmediately(JComponent.java:5086)
at javax.swing.JComponent.paintImmediately(JComponent.java:4896)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:783)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:735)
4

3 に答える 3

2

ballListコードの残りの部分を見ずに、1つの修正は次のように宣言することです。

private final List<Ball> ballList = Collections.synchronizedList(...);

すべてのメソッドの前にそれ自体で同期を試みるすべての操作synchronizedList。これにより、現在のを所定の位置に保持している限り、反復は完全に安全になりますsynchronized(ballList)

于 2012-07-24T02:58:08.107 に答える
1

ここに表示されているコードでは、ballList実際には変更されておらず、複数のスレッドで読み取るのが安全です。他のコードが変更ballListされている可能性があります(上記の@pstは、変更されている可能性があることを指摘していますupdatePosition)。

runおよびメソッドは、paintComponent外部で状態を共有していないため(ballListコードの関連部分で同期しているため)、同期する必要があるようには見えません。

編集:

あなたの編集に基づくと、実際に変更されていないときではなく、1つの短いブロックに対してprocessCollisionsのみ同期化されているように見えますballsLocalballsLocal

synchronized (ballsLocal) {             
  initialSize = ballsLocal.size();
}

同期されていますprocessCollisionsが、暗黙的にに同期されthisます。synchronized何を同期するかを指定せずにキーワードを使用するだけのメソッドが異なるクラスにある場合、this同期される方法は異なります。そのような異なるクラス間で同期する必要がある場合は、ボールクラスが同期を処理するか、共有されるロックが必要です。

于 2012-07-24T02:59:03.127 に答える
0

processCollisions()で、同期ブロックの外側のリストにオブジェクトを追加しています。同期されているように見えるのは1行だけで、サイズを取得している行ですが、後で(最後の方で)リストに追加していることに注意してください。ループが終了するまで、同期されたブロックを閉じる必要はありません。

于 2012-07-24T03:28:44.523 に答える