从多个线程访问单个数据时,如何修复arrayindexoutofboundsexception错误?

4nkexdtk  于 2021-07-06  发布在  Java
关注(0)|答案(0)|浏览(262)

我正在用javagui做一个打字游戏。我间歇性地犯这些错误。

Exception in thread "Thread-4" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 0
    at java.base/java.util.Vector.get(Vector.java:781)
    at GamePanel$DetectBottomThread.run(GamePanel.java:200)

和游戏面板。java:200 line 是

int y = ((JLabel)targetVector.get(i)).getY();

在detectbottomthread中。
这是我的代码(重要方法)

public GamePanel(ScorePanel scorePanel, EditPanel editPanel) {
        // 기억해둔다.
        this.scorePanel = scorePanel;
        this.editPanel = editPanel;

        setLayout(new BorderLayout());
        add(gameGroundPanel, BorderLayout.CENTER);
        add(inputPanel, BorderLayout.SOUTH);

        input.setHorizontalAlignment(JTextField.CENTER); // input JTextField 가운데정렬
        input.setFont(new Font("Aharoni", Font.PLAIN, 20));

        // textfield에서 enter
        input.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JTextField t = (JTextField)(e.getSource());
                String inWord = t.getText(); // 사용자가 입력한 단어
                for (int i=0; i < targetVector.size(); i++) {
                    String text = targetVector.get(i).getText();
                    if(text.equals(inWord)) { // 단어맞추기 성공
                        // 점수 올리기
                        scorePanel.increase();
                        scorePanel.repaintScore();
                        gameGroundPanel.remove(targetVector.get(i)); // 패널에서 라벨 떼기
                        targetVector.remove(i); // targetVector에서 삭제
                        t.setText(null); // input 비우기
                    }
                    // 벡터 마지막원소에서도 일치하는 단어 못찾음
                    if((i == (targetVector.size() - 1)) && !targetVector.get(i).getText().equals(inWord)) {
                        scorePanel.decrease();
                        scorePanel.repaintScore();
                        t.setText(null);
                    }
                    t.requestFocus(); // 엔터 친 후에도 textField에 focus유지
                }

            }
        });
    }
public void gameStart() {
        // 단어생성
        generateWordThread.start();
        // 단어 떨어뜨리기
        dropWordThread.start();
        // 땅에 닿은 단어 감지
        detectBottomThread.start();
    }

    // 단어 생성하는 스레드
    // 정해진 시간마다 단어를 계속 생성한다.....
    // 생성한 단어는 별도의 스레드를 두어 아래로 내려가도록 한다.
    public class GenerateWordThread extends Thread{

        private Vector<JLabel>targetVector = null;

        synchronized void generateWord() {
            JLabel targetLabel = new JLabel("");
            // 단어 한 개 선택
            String newWord = textSource.get();
            targetLabel.setText(newWord);

            // targetLabel 모양
            targetLabel.setHorizontalAlignment(JLabel.CENTER); // JLabel 가운데정렬
            targetLabel.setSize(200, 40);
            targetLabel.setFont(new Font("Aharoni", Font.PLAIN, 20));

            // x좌표 랜덤 설정
            int startX = (int) (Math.random()*gameGroundPanel.getWidth());
            while(true) {
                if ((startX + targetLabel.getWidth()) > gameGroundPanel.getWidth()) 
                    startX = (int) (Math.random()*gameGroundPanel.getWidth());
                else
                    break;
            }

            targetLabel.setLocation(startX,0);

            targetLabel.setOpaque(false); // 배경 투명하게
            targetVector.addElement(targetLabel); // targetVector에 생성한 newWord 추가
            gameGroundPanel.add(targetLabel);
        }

        public GenerateWordThread(Vector<JLabel>targetVector) {
            this.targetVector = targetVector;
        }

        @Override
        public void run() {
            while(true) {
                generateWord();
                gameGroundPanel.repaint();
                try {
                    sleep(6000);
                    //time -= 500; // 시간 점점 빨라지게 하기 위해
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } // end of while
        } // end of run()
    } // end of GenerateWordThread

    // 단어 아래로 내리는 스레드
    public class DropWordThread extends Thread{

        private Vector<JLabel>targetVector = null;

        public DropWordThread(Vector<JLabel>targetVector) {
            this.targetVector = targetVector;
        }

        // targetVector에 들어있는 모든 JLabel들의 y좌표 증가
        @Override
        public void run() {
             while (true){
                 for (int i=0; i<targetVector.size(); i++) {
                    int x = targetVector.get(i).getX();
                    int y = targetVector.get(i).getY();
                    targetVector.get(i).setLocation(x, y+5);
                    gameGroundPanel.repaint();
                } // end of for
                 try {
                        sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
            } // end of while
        } // end of run()
    } // end of DropWordThread

    public class DetectBottomThread extends Thread {

        private Vector<JLabel>targetVector = null;

        public DetectBottomThread(Vector<JLabel>targetVector) {
            this.targetVector = targetVector;
        }

        @Override
        public void run() {
            while(true) {
                for(int i=0; i<targetVector.size(); i++) {
                    int y = ((JLabel)targetVector.get(i)).getY(); // 오류가 자?꾸만..
                    if (y > gameGroundPanel.getHeight()-20) {
                        scorePanel.decreaseLife();
                        gameGroundPanel.remove(targetVector.get(i)); // 패널에서 라벨 떼기
                        targetVector.remove(i); // targetVector에서 삭제
                    }
                }
            } // end of while
        } // end of run()
    }// end of Thread

    }

我不知道如何解决这个问题,因为向量的元素被许多线程同时接近。
我想知道我是否必须使用与vector不同的数据类型,或者是否有使用synchronized方法的解决方案(我知道synchronized方法的概念,但是我还没有找到一种方法来解决这个问题。)
我很抱歉,源代码很长,注解是韩文的。谢谢您

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题