2013-01-08 2 views
0

자바에서 간단한 게임을 쓰는 임.동시 수정 예외 구하기. 문제가 어디 있니? (코드)

public class MainPanel extends JPanel { 
    private Player player = new Player(100, 100, 3, 3); 
    private Point2D targetPoint = new Point2D.Float(130, 350); //Pos on begin 
    private ArrayList<Beam> beams = new ArrayList<Beam>(); 

    public MainPanel() { 
     setPreferredSize(new Dimension(300, 400)); 

     addMouseMotionListener(new MouseMotionHandler()); 
     //Add shortcuts 
     makeShortcut("player.BM1", "F1", new SetBeamModeAction(1)); 
     makeShortcut("player.BM2", "F2", new SetBeamModeAction(2)); 

     //Start threads 
     Thread t = new Thread(new PlayerMoveRunnable()); 
     t.start(); 
     Thread t2 = new Thread(new PlayerShootRunnable()); 
     t2.start(); 
    } 

    public void paintComponent(Graphics g) { 
     Graphics2D g2 = (Graphics2D)g; 
     g2.setColor(Color.BLACK); 
     g2.fillRect(0, 0, 300, 400); 
     //Draw player 
     g2.drawImage(player.getImage(), (int)player.getX(), (int)player.getY(), null); 
     //Draw beams 
     for (Beam beam : beams) { 
      g2.drawImage(beam.getImage(), (int)beam.getX(), (int)beam.getY(), null); 
     } 
    } 

    //Thread running all the time 
    private class PlayerMoveRunnable implements Runnable { 
     public void run() { 
      try { 
       while (true) { 
        player.moveToPoint(targetPoint); 
        repaint(); 
        Thread.sleep(15); 
       } 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    //Thread working all the time 
    private class PlayerShootRunnable implements Runnable { 
     public void run() { 
      try { 
       while (true) { 
        //Choose which beam to shoot (depends on set mode) 
        Thread t; 
        switch (player.getBeamMode()) { 
         case 1: 
          t = new Thread(new BeamMoveRunnable(new Beam1(player.getX()+18, player.getY(), 0, -15))); 
          break; 
         case 2: 
          t = new Thread(new BeamMoveRunnable(new Beam2(player.getX()+18, player.getY(), 0, -30))); 
          break; 
         default: 
          t = null; 
          break; 
        } 
        t.start(); 
        Thread.sleep(200); 
       } 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    private class BeamMoveRunnable implements Runnable { 
     private Beam beam; 

     public BeamMoveRunnable(Beam beam) { 
      this.beam = beam; 
     } 

     public void run() { 
      Beam beam = this.beam; 
      beams.add(beam); 
      try { 
       while (true) { 
        if (beam.getY() <= 0) { 
         beams.remove(beam); 
         break; 
        } 
        beam.move(); 
        repaint(); 
        Thread.sleep(20); 
       } 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

[이 아니 전체 코드 : 여기에 주요 코드입니다. 나는 몇 줄을 잘라 확실 원인이 arent 문제]

임 점점 같은 오류 :

Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException 
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819) 
    at java.util.ArrayList$Itr.next(ArrayList.java:791) 
    at spacecommander.MainPanel.paintComponent(MainPanel.java:53) 
    at javax.swing.JComponent.paint(JComponent.java:1054) 

등등 ...

는 문제가있다? 나는 ConcurrentModificationException이 의미하는 것을 안다. 그러나 나는 여기서 문제가 될 수있는 곳을 모른다. 어쩌면 나는 어떤 동기화를해야 할 것이다. 예 경우 표시하십시오

+0

btw, PlayerShootRunnable은 영원히 반복됩니다. 200 밀리 초마다 새로운 BeamMoveRunnable 스레드가 생성되며,이 스레드는 영원히 실행됩니다. 초당 5 개의 새 스레드를 생성하고 있으며 그 중 어느 것도 종료하지 않습니다. – dashrb

+0

빔이 0 또는 더 큰 위치의 루프가 끊어 지므로 스레드가 끝납니다. –

+0

예, 공정한 포인트. 미안, 나는 그것을 놓쳤다. 여전히 실질적인 스레드 변동, IMHO 것 같습니다. – dashrb

답변

0

스레드 BeamMoveRunnable (이 Runnable 개체를 래핑하는 스레드)에서 arraylists beams을 동시에 수정하는 중 paintComponent 메서드를 수정하는 중입니다. 이것은 예외의 원인입니다.

1

예를 들어 빔의 목록을 다른 스레드에서 수정하고 있습니다. BeamMoveRunnable 컬렉션을 반복하는 동안.

개체 당 스레드를 만드는 것은 꽤 낭비적이고 관리하기 어렵습니다.

각 빔에서 이동하기 위해 주기적으로 하나의 스레드를 호출하는 것이 좋습니다. 광선을 그릴 때 광선을 추가하거나 제거하지 말고 컬렉션에 대한 액세스를 동기화 할 필요가 없습니다.

+0

좋아, 그럼 내가 바꿔서 모든 광선을 움직일 수있는 하나의 실을 만들어 보겠다. 하지만 어쨌든 도움이되지 않을 것 같아요. 페인트 메소드가 페인트하려고 할 때 스레드가 컬렉션을 반복하고 요소 하나를 제거 할 가능성이 있기 때문입니다. 어떻게 방지 할 수 있습니까? –

+0

그래서 내가 말했듯이, 어떤 요소도 제거하지 마십시오. 'paintComponent'에서 볼 수있는 요소 만 제거 할 수 있습니다. –

+0

하지만 응용 프로그램의 성능에 영향을주지 않겠습니까? 아니면 stack overflow 등의 예외를 throw하지 않겠습니까? 새로운 빔이 매 200ms마다 자동으로 추가되기 때문에 게임 몇 분 후에 많은 빔이 생길 수 있습니다. –

1

빔을 반복하기 전에 paintComponent 컬렉션을 만들고 복사본을 사용하여 반복합니다.