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

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

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

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

和游戏面板。java:200 line 是

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

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

  1. public GamePanel(ScorePanel scorePanel, EditPanel editPanel) {
  2. // 기억해둔다.
  3. this.scorePanel = scorePanel;
  4. this.editPanel = editPanel;
  5. setLayout(new BorderLayout());
  6. add(gameGroundPanel, BorderLayout.CENTER);
  7. add(inputPanel, BorderLayout.SOUTH);
  8. input.setHorizontalAlignment(JTextField.CENTER); // input JTextField 가운데정렬
  9. input.setFont(new Font("Aharoni", Font.PLAIN, 20));
  10. // textfield에서 enter
  11. input.addActionListener(new ActionListener() {
  12. public void actionPerformed(ActionEvent e) {
  13. JTextField t = (JTextField)(e.getSource());
  14. String inWord = t.getText(); // 사용자가 입력한 단어
  15. for (int i=0; i < targetVector.size(); i++) {
  16. String text = targetVector.get(i).getText();
  17. if(text.equals(inWord)) { // 단어맞추기 성공
  18. // 점수 올리기
  19. scorePanel.increase();
  20. scorePanel.repaintScore();
  21. gameGroundPanel.remove(targetVector.get(i)); // 패널에서 라벨 떼기
  22. targetVector.remove(i); // targetVector에서 삭제
  23. t.setText(null); // input 비우기
  24. }
  25. // 벡터 마지막원소에서도 일치하는 단어 못찾음
  26. if((i == (targetVector.size() - 1)) && !targetVector.get(i).getText().equals(inWord)) {
  27. scorePanel.decrease();
  28. scorePanel.repaintScore();
  29. t.setText(null);
  30. }
  31. t.requestFocus(); // 엔터 친 후에도 textField에 focus유지
  32. }
  33. }
  34. });
  35. }
  1. public void gameStart() {
  2. // 단어생성
  3. generateWordThread.start();
  4. // 단어 떨어뜨리기
  5. dropWordThread.start();
  6. // 땅에 닿은 단어 감지
  7. detectBottomThread.start();
  8. }
  9. // 단어 생성하는 스레드
  10. // 정해진 시간마다 단어를 계속 생성한다.....
  11. // 생성한 단어는 별도의 스레드를 두어 아래로 내려가도록 한다.
  12. public class GenerateWordThread extends Thread{
  13. private Vector<JLabel>targetVector = null;
  14. synchronized void generateWord() {
  15. JLabel targetLabel = new JLabel("");
  16. // 단어 한 개 선택
  17. String newWord = textSource.get();
  18. targetLabel.setText(newWord);
  19. // targetLabel 모양
  20. targetLabel.setHorizontalAlignment(JLabel.CENTER); // JLabel 가운데정렬
  21. targetLabel.setSize(200, 40);
  22. targetLabel.setFont(new Font("Aharoni", Font.PLAIN, 20));
  23. // x좌표 랜덤 설정
  24. int startX = (int) (Math.random()*gameGroundPanel.getWidth());
  25. while(true) {
  26. if ((startX + targetLabel.getWidth()) > gameGroundPanel.getWidth())
  27. startX = (int) (Math.random()*gameGroundPanel.getWidth());
  28. else
  29. break;
  30. }
  31. targetLabel.setLocation(startX,0);
  32. targetLabel.setOpaque(false); // 배경 투명하게
  33. targetVector.addElement(targetLabel); // targetVector에 생성한 newWord 추가
  34. gameGroundPanel.add(targetLabel);
  35. }
  36. public GenerateWordThread(Vector<JLabel>targetVector) {
  37. this.targetVector = targetVector;
  38. }
  39. @Override
  40. public void run() {
  41. while(true) {
  42. generateWord();
  43. gameGroundPanel.repaint();
  44. try {
  45. sleep(6000);
  46. //time -= 500; // 시간 점점 빨라지게 하기 위해
  47. } catch (InterruptedException e) {
  48. // TODO Auto-generated catch block
  49. e.printStackTrace();
  50. }
  51. } // end of while
  52. } // end of run()
  53. } // end of GenerateWordThread
  54. // 단어 아래로 내리는 스레드
  55. public class DropWordThread extends Thread{
  56. private Vector<JLabel>targetVector = null;
  57. public DropWordThread(Vector<JLabel>targetVector) {
  58. this.targetVector = targetVector;
  59. }
  60. // targetVector에 들어있는 모든 JLabel들의 y좌표 증가
  61. @Override
  62. public void run() {
  63. while (true){
  64. for (int i=0; i<targetVector.size(); i++) {
  65. int x = targetVector.get(i).getX();
  66. int y = targetVector.get(i).getY();
  67. targetVector.get(i).setLocation(x, y+5);
  68. gameGroundPanel.repaint();
  69. } // end of for
  70. try {
  71. sleep(100);
  72. } catch (InterruptedException e) {
  73. e.printStackTrace();
  74. }
  75. } // end of while
  76. } // end of run()
  77. } // end of DropWordThread
  78. public class DetectBottomThread extends Thread {
  79. private Vector<JLabel>targetVector = null;
  80. public DetectBottomThread(Vector<JLabel>targetVector) {
  81. this.targetVector = targetVector;
  82. }
  83. @Override
  84. public void run() {
  85. while(true) {
  86. for(int i=0; i<targetVector.size(); i++) {
  87. int y = ((JLabel)targetVector.get(i)).getY(); // 오류가 자?꾸만..
  88. if (y > gameGroundPanel.getHeight()-20) {
  89. scorePanel.decreaseLife();
  90. gameGroundPanel.remove(targetVector.get(i)); // 패널에서 라벨 떼기
  91. targetVector.remove(i); // targetVector에서 삭제
  92. }
  93. }
  94. } // end of while
  95. } // end of run()
  96. }// end of Thread
  97. }

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

暂无答案!

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

相关问题