Threads em Java

7 respostas
java
N

Eu estou fazendo um trabalho para a disciplina de programação concorrente, no qual estou implementando o problema do Pare-Siga em uma simulação do Pacman. Compilando uma só vez, as vezes eu executo e dá certo, outras vezes dá errado, depois dá certo de novo, depois errado, não sei o que se passa.
Não aparece nenhum erro, algumas vezes. Cada thread é responsável pela movimentação de um personagem na tela. As vezes, todos se movem, tudo certinho, outra hora, um fica parado o tempo todo, outra hora todos se mexem, outra hora um outro personagem fica parado, isso tudo com o mesmo .class, só executo de novo e fica diferente, dando certo ou não.
Outras vezes, aparece o seguinte erro:

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
        at com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(AbstractMasterTimer.java:344)
        at com.sun.scenario.animation.AbstractMasterTimer$MainLoop.run(AbstractMasterTimer.java:267)
        at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:506)
        at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
        at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$404(QuantumToolkit.java:319)
        at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
        at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
        at java.lang.Thread.run(Thread.java:745)

Não sei bem qual é a classe ou a parte do código que está gerando essas situações, mas vou colocar aqui algumas das classes.

Controle da tela:

package controles; // ControlePacman se encontra no pacote controles

// As importações aqui...
public class ControlePacman implements Initializable {

  // Atributos da classe
  @FXML private AnchorPane anchorBase; 
  @FXML private Button sair;
  @FXML public ImageView imgPacman;
  Pacman pacman;
  @FXML public ImageView imgFantasminha;
  Fantasminha fantasminha;
  @FXML public ImageView imgFantasmaRight;
  FantasmaRight fantasmaRight;
  @FXML public ImageView imgFantasmaLeft;
  FantasmaLeft fantasmaLeft;
  @FXML private Button botaoVoltar;
  @FXML private Label labelModo;
  @FXML private Label labelMusica;
  public boolean pacmanPassando;
  public boolean fantasmaPassando;
  public ControleInicio tela;
  public static enum Status {DO, DONT}; // Opcoes de um personagem, se deve ser mover ou nao

/* *******************************************************************
 * Metodo: ControlePacman
 * Funcao: construtor da classe de mesmo nome
 * Parametros: nao possui parametros
 * Retorno: nao possui retorno
 ******************************************************************** */
  public ControlePacman() {
    imgFantasminha = new ImageView(); // Inicializando ImageView
    imgFantasmaRight = new ImageView(); // Inicializando ImageView
    imgFantasmaLeft = new ImageView(); // Inicializando ImageView
    imgPacman = new ImageView(); // Inicializando ImageView
    anchorBase = new AnchorPane(); // Inicializando AnchorPane
    sair = new Button(); // Incializando Button
    botaoVoltar = new Button(); // Inicializando Button
  } // Fim do construtor

/* *******************************************************************
 * Metodo: initialize
 * Funcao: primeiro metodo executado quando a tela e chamada
 * Parametros: URL e ResourceBundle
 * Retorno: void
 ******************************************************************** */
  @Override
  public void initialize(URL location, ResourceBundle resources) {
    imgFantasmaRight.setImage(new Image("/imagens/fantasmaDO2.png")); // Definindo a imagem
    imgFantasmaLeft.setImage(new Image("/imagens/fantasmaDO1.png")); // Definindo a imagem
    pacman = new Pacman(); // Inicializando a thread
    fantasminha = new Fantasminha(); // Inicializando a thread
    fantasmaRight = new FantasmaRight(); // Inicializando a thread
    fantasmaLeft = new FantasmaLeft(); // Inicializando a thread
    fantasminha.setTela(this); // Passando o controle para fantasminha
    fantasminha.start(); // Colocando-a em estado de pronto
    pacman.setTela(this); // Passando o controle para pacman
    pacman.start(); // Colocando-a em estado de pronto
    fantasmaRight.setTela(this); // Passando o controle para fantasmaRight
    fantasmaRight.start(); // Colocando-a em estado de pronto
    fantasmaLeft.setTela(this); // Passando o controle para fantasmaLeft
    fantasmaLeft.start(); // Colocando-a em estado de pronto
  } // Fim de initialize

/* *******************************************************************
 * Metodo: setTela
 * Funcao: receber o controle da tela de inicio
 * Parametros: objeto de ControleInicio
 * Retorno: void
 ******************************************************************** */
  public void setTela(ControleInicio tela) {
    this.tela = tela;
  } // Fim de setTela

/* *******************************************************************
 * Metodo: setVelocidade
 * Funcao: configurar as velocidades dos personagens
 * Parametros: dois inteiros, as velocidades
 * Retorno: void
 ******************************************************************** */
  public void setVelocidade(int speed1, int speed2) {
    fantasminha.setVelocidade(speed1);
    fantasmaRight.setVelocidade(speed1);
    fantasmaLeft.setVelocidade(speed1);
    pacman.setVelocidade(speed2);
  } // Fim de setVelocidade
/* *******************************************************************
 * Metodo: getPassando
 * Funcao: avisa se um dos personagens esta passando pela area compartilhada
 * Parametros: String com o nome do personagem
 * Retorno: boolean
 ******************************************************************** */
  public boolean getPassando(String quem) {
    switch(quem) {
      case "pacman": // Para o caso do pacman
        return pacmanPassando; // Retorna o valor verdade
      case "fantasminha": // Para o caso do fantasminha
        return fantasmaPassando; // Retorna o valor verdade
    } // Fim do switch
    return false;
  } // Fim de getPassando

/* *******************************************************************
 * Metodo: setPassando
 * Funcao: para informar o controle se algum personagem esta passando
 *         pela area compartilhada
 * Parametros: um boolean e o nome do personagem
 * Retorno: void
 ******************************************************************** */
  public void setPassando(boolean flag, String quem) {
    switch(quem) {
      case "pacman": // Para o caso do pacman
        pacmanPassando = flag; // Registra o valor verdade
      case "fantasminha": // Para o caso do fantasminha
        fantasmaPassando = flag; // Registra o valor verdade
    } // Fim do switch
  } // Fim de setPassando

 /* *******************************************************************
 * Metodo: moveEmY
 * Funcao: mover os personagens pelo eixo y
 * Parametros: double, inteiro e string
 * Retorno: animacao da classe TranslateTransition
 ******************************************************************** */
  public TranslateTransition moveEmY(double tempo, int destino, String quem) {
    TranslateTransition transicao = new TranslateTransition(); // Criando e instanciando transicao

    Platform.runLater(new Runnable() {
      @Override
      public void run() {

        transicao.setDuration(Duration.seconds(tempo)); // Definindo duracao da transicao

        switch(quem) { // Para definir quem esta se movendo
          case "fantasminha": // Se for um movimento de Fantasminha
            transicao.setNode(imgFantasminha);
            break;
          case "fantasmaRight": // Se for um movimento de FantasmaRight
            transicao.setNode(imgFantasmaRight);
            break;
          case "fantasmaLeft": // Se for um movimento de FantasmaLeft
            transicao.setNode(imgFantasmaLeft);
            break;
          case "pacman": // Se for um movimento de Pacman
            transicao.setNode(imgPacman);
            break;
          default:
            System.out.println("Algo deu errado!");
        }

        transicao.setToY(destino); // Movendo o personagem ate o local desejado
        transicao.play(); // Autoexplicativo

      } // Fim de run

    }); // Fim de Platform

    return transicao;
  } // Fim de moveEmY

/* *******************************************************************
 * Metodo: moveEmX
 * Funcao: mover os personagens no eixo X
 * Parametros: double, int e string
 * Retorno: animacao da classe TranslateTransition
 ******************************************************************** */
  public TranslateTransition moveEmX(double tempo, int destino, String quem) {
    TranslateTransition transicao = new TranslateTransition(); // Criando e instanciando a transicao
    
    Platform.runLater(new Runnable() {
      @Override
      public void run() {
        
        transicao.setDuration(Duration.seconds(tempo)); // Definindo a duracao da transicao

        switch(quem) { // Para definir quem esta se movendo
          case "fantasminha": // Se for um movimento de Fantasminha
            transicao.setNode(imgFantasminha);
            break;
          case "fantasmaRight": // Se for um movimento de FantasmaRight
            transicao.setNode(imgFantasmaRight);
            break;
          case "fantasmaLeft": // Se for um movimento FantasmaLeft
            transicao.setNode(imgFantasmaLeft);
            break;
          case "pacman": // Se for for um movimento de Pacman
            transicao.setNode(imgPacman);
            break;
        } // Fim de switch

        transicao.setToX(destino); // Movendo o personagem ate o local desejado
        transicao.play(); // Autoexplicativo
    
      } // Fim de run

    }); // Fim de Platform

    return transicao;

  } // Fim de moveEmX

/* *******************************************************************
 * Metodo: chegouDireita
 * Funcao: informar quando algum personagem entrou na regiao critica
 *         pelo lado direito
 * Parametros: void
 * Retorno: void
 ******************************************************************** */
  public void chegouDireita() {
    controleEsquerda(Status.DONT); // Chamando metodo controleEsquerda
  } // Fim de chegouDireita

/* *******************************************************************
 * Metodo: saiuEsquerda
 * Funcao: informar quando algum perosnagem deixou a regiao critica pelo
 *         lado esquerdo
 * Parametros: void
 * Retorno: void
 ******************************************************************** */
  public void saiuEsquerda(String quem) {
    switch(quem) {
      case "pacman":
        if (fantasmaPassando)
          controleEsquerda(Status.DONT); // Chamando o metodo controleEsquerda
        controleEsquerda(Status.DO);
        break;
      case "fantasminha":
        if (pacmanPassando)
          controleEsquerda(Status.DONT);
        controleEsquerda(Status.DO);
        break;
    } // Fim do switch
  } // Fim de saiu Esquerda

/* *******************************************************************
 * Metodo: chegouEsquerda
 * Funcao: informar quando algum personagem chegou na regiao critica
 *         pelo lado esquerdo
 * Parametros: void
 * Retorno: void
 ******************************************************************** */
  public void chegouEsquerda() {
    controleDireita(Status.DONT); // Chamando o metodo controleDireita
  } // Fim de chegouEsquerda

/* *******************************************************************
 * Metodo: saiuDireita()
 * Funcao: informar quando algum personagem deixou a regiao critica pelo
 *         pelo lado direito
 * Parametros: void
 * Retorno: void
 ******************************************************************** */
  public void saiuDireita(String quem) {
    switch(quem) {
      case "pacman":
        if (fantasmaPassando)
          controleDireita(Status.DONT); // Chamando o metodo controleEsquerda
        controleDireita(Status.DO);
        break;
      case "fantasminha":
        if (pacmanPassando)
          controleDireita(Status.DONT);
        controleDireita(Status.DO);
        break;
    } // Fim do switch
  } // Fim de saiuDireita

/* *******************************************************************
 * Metodo: controleDireita
 * Funcao: fazer o fantasma da esquerda levnatar ou abaixar a placa
 * Parametros: Status
 * Retorno: void
 ******************************************************************** */
  public void controleDireita(Status status) {
    Platform.runLater(new Runnable() {
      @Override
      public void run() {
        if (status == Status.DONT) {
          imgFantasmaLeft.setImage(new Image("/imagens/fantasmaDONT1.png")); // Levantando a placa
        } // Fim do if
        else {
          imgFantasmaLeft.setImage(new Image("/imagens/fantasmaDO1.png")); // Abaixando a placa
        } // Fim do else
      } // Fim de run
    }); // Fim de Platform
  } // Fim de controleDireita

/* *******************************************************************
 * Metodo: controleEsquerda
 * Funcao: fazer o fantasma da direita levantar ou abaixar a placa
 * Parametros: Status
 * Retorno: void
 ******************************************************************** */
  public void controleEsquerda(Status status) {
    Platform.runLater(new Runnable() {
      @Override
      public void run() {
        if (status == Status.DONT) {
          imgFantasmaRight.setImage(new Image("/imagens/fantasmaDONT2.png")); // Levantando a placa
        } // Fim de if
        else {
          imgFantasmaRight.setImage(new Image("/imagens/fantasmaDO2.png")); // Levantando a placa
        } // Fim de else
      } // Fim de run
    }); // Fim de Platform
  } // Fim de controleEsquerda

/* *******************************************************************
 * Metodo: fechar
 * Funcao: encerrar o programa
 * Parametros: evento
 * Retorno: void
 ******************************************************************** */
  @FXML
  public void fechar(ActionEvent event) {
    System.exit(0); // Encerrando o programa
  } // Fim de fechar

} // Fim de ControlePacman

Da thread que comanda o Pacman:

package personagens; // Pacman se encontra no pacote personagens

// As importações aqui...

public class Pacman extends Thread { // E uma thread

  // Atributos da classe Pacman
  public ControlePacman tela;
  private int velocidade;
  private int contador;
  private Timeline tempo;

/* *******************************************************************
 * Metodo: Pacman
 * Funcao: metodo construtor dessa classe
 * Parametros: void
 * Retorno: nao retorna nada
 ******************************************************************** */
  public Pacman() {
    velocidade = 1; // Inicializando a velocidade como 1
    contador = 0; // Inicializando o contador como 1
  } // Fim de construtor

/* *******************************************************************
 * Metodo: setTela
 * Funcao: recebendo o controle
 * Parametros: objeto de ControlePacman
 * Retorno: void
 ******************************************************************** */
  public void setTela(ControlePacman tela) {
    this.tela = tela;
  } // Fim de setTela

/* *******************************************************************
 * Metodo: setVelocidade
 * Funcao: configurar a velocidade do fantasma da direita
 * Parametros: inteiro com a velocidade
 * Retorno: void
 ******************************************************************** */
  public void setVelocidade(int velocidade) {
    this.velocidade = velocidade;
  } // Fim de setVelocidade

/* *******************************************************************
 * Metodo: run
 * Funcao: primeiro metodo a ser executado quando a thread for acionada
 * Parametros: void
 * Retorno: void
 ******************************************************************** */
  @Override
  public void run() {

    try {

      sleep(1000); 
    
      tela.imgPacman.setOpacity(1); // Torna visivel o pacman

      tempo = new Timeline(new KeyFrame(Duration.seconds(0), (a) -> {
        tela.moveEmX(velocidade, 55, "pacman");
      }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmY(velocidade, 250, "pacman");
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmX(velocidade, 180, "pacman");
        }));
        tempo.play();

      trajeto(); // Chamando o metodo trajeto

    } catch(Exception pac) {
      pac.getStackTrace();
    }

  } // Fim de run

/* *******************************************************************
 * Metodo: trajeto
 * Funcao: funcao recursiva que define o trajeto performado pelo pacman
 * Parametros: void
 * Retorno: void
 ******************************************************************** */
  private void trajeto() {

    try {

      tempo = new Timeline(new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
        tela.moveEmX(velocidade, 300, "pacman");
      }),
      new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
        tela.moveEmY(velocidade, 360, "pacman");
      }),
      new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
        tela.moveEmX(velocidade, 180, "pacman");
      }),
      new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
        tela.moveEmY(velocidade, 485, "pacman");
      }),
      new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
        tela.moveEmX(velocidade, 300, "pacman");
      }),
      new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
        tela.moveEmX(velocidade, 180, "pacman");
      }),
      new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
        tela.moveEmY(velocidade, 360, "pacman");
      }),
      new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
        tela.moveEmX(velocidade, 300, "pacman");
      }),
      new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
        tela.moveEmY(velocidade, 240, "pacman");
      }),
      new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
        tela.moveEmX(velocidade, 180, "pacman");
      }));
      tempo.play();

      sleep(velocidade * contador);

    while(tela.getPassando("fantasminha")) {
      // Esperando o fantasma passar pela zona critica
      sleep(500);
    } // Fim do while

    tempo = new Timeline(new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
      tela.setPassando(true, "pacman"); // Avisando que a pista esta ocupada
      tela.chegouEsquerda(); // Pedindo para o fantasma fechar a pista
    }),
    new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
      tela.moveEmY(velocidade, 125, "pacman");
    }),
    new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
      tela.moveEmX(velocidade, 540, "pacman");
    }),
    new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
      tela.moveEmY(velocidade, 0, "pacman");
    }),
    new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
      tela.setPassando(false, "pacman");// Avisando que a pista esta liberada
      tela.saiuDireita("pacman"); // Pedindo para o fantasma abaixar a placa
    }),
    new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
      tela.moveEmX(velocidade, 650, "pacman");
    }),
    new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
      tela.moveEmX(velocidade, 540, "pacman");
    }));
    tempo.play();
    
    sleep(velocidade * contador);

    while(tela.getPassando("fantasminha")) {
      // Esperando o fantasma atravessar a regiao critica
      sleep(500);
    } // Fim de while

    tempo = new Timeline(new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
      tela.setPassando(true, "pacman"); // Avisando que a pista esta ocupada
      tela.chegouDireita(); // Pedindo para o fantasma fechar a pista
    }),
    new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
      tela.moveEmY(velocidade, 125, "pacman");
    }),
    new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
      tela.moveEmX(velocidade, 180, "pacman");
    }),
    new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
      tela.moveEmY(velocidade, 240, "pacman");
    }),
    new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
      tela.setPassando(false, "pacman"); // Avisando que a pista esta livre
      tela.saiuEsquerda("pacman"); // Pedindo para o fantasma liberar a pista
    }));
    tempo.play();

    sleep(velocidade * contador);

    trajeto(); // Chamada recursiva

    } catch (Exception pac) {
      pac.getStackTrace();
    }
  } // Fim de trajeto
  
} // Fim de Pacman

Da classe de um dos fantasmas:

package personagens; // Fantasminha esta no pacote personagens

// importações...

public class Fantasminha extends Thread {

  // Atributos dessa classe
  public ControlePacman tela;
  private int velocidade;
  private int contador;
  private Timeline tempo;

/* *******************************************************************
 * Metodo: Fanstaminha
 * Funcao: metodo construtor dessa classe
 * Parametros: void
 * Retorno: nao retorna nada
 ******************************************************************** */
  public Fantasminha() {
    velocidade = 1; // Inicializando a velocidade como 1
    contador = 0; // Inicializando o contador com 0
  } // Fim do construtor

/* *******************************************************************
 * Metodo: setTela
 * Funcao: recebendo o controle
 * Parametros: objeto de ControlePacman
 * Retorno: void
 ******************************************************************** */
  public void setTela(ControlePacman tela) {
    this.tela = tela;
  } // Fim de setTela

/* *******************************************************************
 * Metodo: setVelocidade
 * Funcao: configurar a velocidade do fantasma da direita
 * Parametros: inteiro com a velocidade
 * Retorno: void
 ******************************************************************** */
  public void setVelocidade(int velocidade) {
    this.velocidade = velocidade;
  } // Fim de setVelocidade

/* *******************************************************************
 * Metodo: run
 * Funcao: primeiro metodo a ser executado quando a thread for acionada
 * Parametros: void
 * Retorno: void
 ******************************************************************** */
  @Override
  public void run() {

    try {

      tela.imgFantasminha.setOpacity(1); // Deixando o fantasma visivel

      tempo = new Timeline(new KeyFrame(Duration.seconds(0), (a) -> {
        tela.moveEmY(velocidade, 175, "fantasminha");
      }),
      new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
        tela.moveEmY(velocidade, 290, "fantasminha");
      }));
      tempo.play(); // Performando a animacao acima

      sleep(velocidade * contador);

      trajeto(); // Chamando a funcao trajeto

    } catch(Exception pac) {
      pac.getStackTrace();
    }

  } // Fim de run

/* *******************************************************************
 * Metodo: trajeto
 * Funcao: funcao recursiva que define o trajeto feito pelo fantasma
 * Parametros: void
 * Retorno: void
 ******************************************************************** */
  private void trajeto() {

    try {

      tempo = new Timeline(new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmX(velocidade, -120, "fantasminha");
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmY(velocidade, 420, "fantasminha");
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmX(velocidade, 0, "fantasminha");
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmY(velocidade, 540, "fantasminha");
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmX(velocidade, -120, "fantasminha");
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmX(velocidade, 0, "fantasminha");
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmY(velocidade, 420, "fantasminha");
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmX(velocidade, -120, "fantasminha");
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmY(velocidade, 290, "fantasminha");
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmX(velocidade, 0, "fantasminha");
        }));
      tempo.play();
      sleep(velocidade * contador);

      while(tela.getPassando("pacman")) {
        // Esperando o pacman atravessar a regiao critiva
        sleep(500);
      } // Fim de while

      tempo = new Timeline(new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.setPassando(true, "fantasminha"); // Avisando que a pista esta ocupada
          tela.chegouDireita(); // Pedindo para o outro fantasma fechar a pista
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmY(velocidade, 175, "fantasminha");
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmX(velocidade, -360, "fantasminha");
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmY(velocidade, 60, "fantasminha");
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.setPassando(false, "fantasminha"); // Avisando que a pista esta livre
          tela.saiuEsquerda("fantasminha"); // Pedindo para o outro fantasma liberar a pista
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmX(velocidade, -480, "fantasminha");
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmX(velocidade, -360, "fantasminha");
        }));
      tempo.play();
      sleep(velocidade * contador);

      while(tela.getPassando("pacman")) {
        // Esperando, caso o pacman esteja atravessando a regiao critiva
        sleep(500);
      } // Fim de while

      tempo = new Timeline(new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.setPassando(true, "fantasminha"); // Sinalizando que a pista esta sendo usada
          tela.chegouEsquerda(); // Pedindo para o outro fantasma levnatar a placa
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmY(velocidade, 175, "fantasminha");
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmX(velocidade, 0, "fantasminha");
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.moveEmY(velocidade, 290, "fantasminha");
        }),
        new KeyFrame(Duration.seconds(++contador * velocidade), (b) -> {
          tela.setPassando(false, "fantasminha"); // Avisando que a pista esta livre
          tela.saiuDireita("fantasminha"); // Pedindo para o outro fantasma abaixar a placa
      }));
      tempo.play();

      trajeto(); // Chamada recursiva

    } catch (Exception pac) {
      pac.getStackTrace();
    }
  } // Fim de trajeto

} // Fim de Fantasminha

Alguém pode me dar uma luz?

7 Respostas

darlan_machado

NPEs ocorrem em 2 situações:

  • Você está invocando um método em um objeto que não foi instanciado
  • Você está acessando uma variável em um objeto que não foi instanciado

Algo como

Pessoa pessoa;
pessoa.getNome();//NPE, você não fez pessoa = new Pessoa();

Precisa debugar e verificar em que ponto isso ocorre e, por que.

peczenyj

darlan isso pode ser mais complicado pq o NPE vem da biblioteca.

eu vi uma pessoa comentando q teve esse problema e foi pq ela deu o run em outra thread e ai um componente era nulo e deu o maior xabu

eu acho q rolou uma confusaozinha no código e algo foi feito na ordem errada mas eh um código bem grande então fica dificil - eu tentaria comentar tudo e ir descomentando o código aos poucos, ate descobrir onde q os comportamentos estranhos começam

rmendes08

na verdade a coisa já começa errada usando várias threads para manipular a interface gráfica …

N

Vou procurar alguma coisa assim, obrigada

darlan_machado

Sim, provavelmente algo está sendo passado antes de ter sido instanciado…

N

Ahh, sim. Vou fazer isso, obrigada pela explicação

N

É que o trabalho da disciplina é assim mesmo, temos que usar várias threads na interface gráfica, porque o professor quer que visualizemos as complicações que surgem quando duas threads tentam acessar a mesma variável.

Criado 7 de agosto de 2018
Ultima resposta 8 de ago. de 2018
Respostas 7
Participantes 4