>

스레드를 사용하지 않지만 다음과 같은 오류가 계속 발생합니다.

""AWT-EventQueue-0 "스레드 java.util.ConcurrentModificationException 예외"

내 코드는 다음과 같습니다 :

@Override
public void paint(Graphics g) {
    for(Rectangles emp: shapes.list) {
        //Loop through all rectangle objects
        for(int[] temp: emp.arr) {
            //Loop through each objects array
            g.drawRect(temp[0], temp[1], 20, 20);
    g.drawRect(20, 20, 20, 20);
        }
    }
}

다른 클래스의 메소드도 paint 메소드 근처에서 아주 반복해서 실행되어 문제를 일으킬 수 있습니다.

public class Shapes {
LinkedList<Rectangles> list  = new LinkedList<Rectangles>();
Random rand = new Random();
void newshape() {
    int shape = rand.nextInt(7);
    switch(shape) {
        case 0:
            list.add(makeSquare());
            break;
        case 1:
            list.add(makeLine());
            break;
        case 2:
            list.add(makeTShape());
            break;
        case 3:
            list.add(makeLShape());
            break;
        case 4:
            list.add(makeJShape());
            break;
        case 5:
            list.add(makeZShape());
            break;
        case 6:
            list.add(makeSShape());
            break;
        }
    }

새 모양을 만든 마지막 순간부터 1 초가 지난 경우 newshape () 메서드를 호출하는 tick () 메서드와 함께 Notch 게임 루프를 사용하고 있습니다. 그런 다음 페인트 방법이 호출됩니다.

public void run(Game game) {
    while(true) {
        lastshapemake = System.nanoTime();
        long lastTime = System.nanoTime();
        double Target_FPS = 60.0;
        double ns = 1000000000 / Target_FPS;
        double delta = 0;
        while(running) { 
            long now = System.nanoTime();
            delta += (now - lastTime) / ns;
            lastTime = now;
            while(delta >= 1) {
                tick();
                delta--;
            }
            if(running) {
                game.repaint();
            }
        }   
    }
}


  • 답변 # 1

    문제는 당신이 그것을 깨닫지 못하더라도여러 개의 쓰레드를 사용하고 있다는 것입니다 :

    <올>

    주요 스레드

    스윙 UI 스레드

    스윙 (및 대부분의 GUI 프레임 워크)은 단 하나의 스레드 만 GUI 및 GUI가 의존하는 모든 데이터를 조작해야한다는 의미에서 단일 스레드입니다.

    참고 : Swing 스레딩 모델은 왜 잘못된 것으로 간주되며 어떻게해야합니까?

    와이즈 비즈  방법은 즉시 페인트하지 않습니다. 이벤트 대기열에 이벤트를 넣고 Swing 스레드가 해당 이벤트를 가져 오면 다시 그리기 코드를 실행합니다.

    와이즈 비즈 동안  게시하지 않은 방법은 repaint 에서 반복하는 것과 동일한 목록을 업데이트하는 것입니다.  방법과 tick 때문에  방법은 때때로 당신의 paint 와 정확히 동시에 실행됩니다  메소드로 인해 ConcurrentModificationExceptions가 발생합니다.

    그 주위에는 몇 가지 방법이 있습니다.

    <올>

    이중 버퍼링을 사용하고 메인 스레드가 보이지 않는 버퍼를 업데이트하도록하고 repaint 메소드가 버퍼가 준비되면 버퍼를 표시하도록 할 수 있습니다.

    paint 를 사용하여 Swing 스레드에서 모든 것을 실행할 수 있습니다.  또는 tick  (당신은 당신의 EventQueue.invokeLater 를 예약 할 수 있습니다  방법))

    javax.swing.Timer 에서 목록을 복사 할 수 있습니다  그것을 반복하기 전에 방법. 그러나 여러 스레드를 사용하고 있으므로 특별한 예방 조치를 취하지 않으면 데이터 경쟁이 발생할 수 있습니다. 당신은 tick 를 사용할 수 있습니다  평범한 paint 대신 또는 CopyOnWriteArrayList 를 사용하십시오.  일반 목록을 하나로 바꾸려면 한 스레드의 변경 사항을 다른 스레드에 안전하게 게시합니다.

  • 답변 # 2

    ConcurrentModificationException은 스레드와 관련이 없습니다.

    의미 : 다음 타임 라인에서 'Z'지점에 있습니다.

    X 지점에서는 컬렉션에서 반복자를 가져옵니다.

    Y 지점 (X 이후)에서 컬렉션은 누군가에 의해 수정됩니다 (다른 스레드 또는 자신의 스레드에있을 수 있음).

    Z 지점 (Y 이후)에서 X에서 얻은 반복자에 대한 작업을 호출합니다.

    ArrayList 를 입력하면 반복자를 작성합니다.  차단하고 당신은 Collections.synchronizedList 를 호출  for 루프가 반복 될 때마다 해당 반복자의 작업.

    코드에서 수정이 발생하는 위치를 알 수 없습니다 (수행하지 않음;for 루프 내에서 collection.remove (x)와 같은 간단한 작업으로 인해 for (Type elem : someCollection) 가 발생할 수 있습니다 붙여 넣은 스 니펫에서는이 작업을 수행하지 않습니다.)

    스윙으로 생각하지 않더라도 여러 개의 스레드를 가질 수 있습니다. 따라서 해당 스 니펫이 실제로 모든 것이라면 다른 스레드가 관여하고 next 를 수정합니다.  또는 ConcurrentModificationException 의 항목 중 하나 .

    shapes

관련 자료

  • 이전 animate ()에 대해 javascript/jQuery로 중요!
  • 다음 c# - 몇 시간/일이 지 났는지 확인