首页 > 解决方案 > 线程类方法运行内部无限循环

问题描述

我有一个用线程运行的小动画。我用两个按钮暂停和播放动画。这是run方法中的代码。

public void run(){
    while(true){
      if(!exitFlag)
        randomBall();
    }
}

当我第一次点击播放时,我启动线程并且动画运行,但是当我点击暂停并再次点击播放时,动画不起作用。发生了一件奇怪的事情,当我添加 时System.out.println("here"),程序运行良好。

public void run(){

    while(true){
      System.out.println("here");
      if(!exitFlag)
        randomBall();
    }
}

我无法弄清楚我在这里做错了什么。这是我的完整代码。

import java.applet.Applet;
import java.awt.Graphics;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Button;
import java.awt.Color;
import java.util.Random;

public class Main extends Applet implements Runnable{
  Button play;
  Button pause;
  int xpos;
  int ypos;
  boolean right;
  int randomYInc; //random x position increment
  int randomXInc; //random y position increment
  boolean top;
  boolean firstTime = true;
  boolean exitFlag = false;
  Thread th;
  Random rand;

  public void init(){
    play = new Button("play");
    pause = new Button("pause");
    MyHandler mh = new MyHandler();
    play.addActionListener(mh);
    pause.addActionListener(mh);
    add(play);
    add(pause);
    th = new Thread(this);
    xpos = 0;
    ypos = 50;
    right = true;
    rand = new Random();
    randomize();
  }

  public void randomize(){
    randomYInc = rand.nextInt((20 - 10) + 10) + 10;
    randomXInc = rand.nextInt((20 - 10) + 10) + 10;
  }

  private class MyHandler implements ActionListener{

    public void actionPerformed(ActionEvent e){
      if(e.getSource() == play){
        if(firstTime){
          th.start();
          firstTime = false;
        }else{
          exitFlag = false;    
        }
      }else if(e.getSource() == pause){
        exitFlag = true;
        //try{th.wait();}catch(Exception ex){}
      }
    }

  }

  public void paint(Graphics g){
    g.setColor(Color.blue);
    g.fillOval(xpos, ypos, 30, 30);
  }

  public void run(){
    while(true){
      if(!exitFlag)
        randomBall();
    }
  }

  public void randomBall(){
    if(right && xpos < 270){ //did not hit right border yet
      if(xpos + randomXInc > 270){
        xpos = 270;
      }else{
        xpos += randomXInc;
      }

      if(ypos > 0 && top){ //did not hit top border yet
        if(ypos - randomYInc < 0){
          ypos = 0;
        }else{
          ypos -= randomYInc;
        }
      }

      if(ypos < 270 && !top){ //did not hit bottom border yet
        if(ypos + randomYInc > 270){
          ypos = 270;
        }else{
          ypos += randomYInc;
        }
      }
    }

    if(!right && xpos > 0){ //did not hit left border yet
      if(xpos - randomXInc < 0){
        xpos = 0;
      }else{
        xpos -= randomXInc;
      }

      if(ypos > 0 && top){ //did not hit top border yet
        if(ypos - randomYInc < 0){
          ypos = 0;
        }else{
          ypos -= randomYInc;
        }
      }

      if(ypos < 270 && !top){ //did not hit bottom border yet
        if(ypos + randomYInc > 270){
          ypos = 270;
        }else{
          ypos += randomYInc;
        }
      }
    }

    //conditions to change ball directions when it hits a border
    if(xpos <= 0){
      right = true;
      top = true;
      randomize();
    }else if(xpos >= 270){
      right = false;
      top = false;
      randomize();
    }else if(ypos <= 0){
      right = true;
      top = false;
      randomize();
    }else if(ypos >= 270){
      right = false;
      top = true;
      randomize();
    }

    repaint();

    try{
      Thread.sleep(80);
    }catch(Exception ex){}
  }
}

标签: java

解决方案


你没有显示所有你的代码,但我想它exitFlag没有被标记为volatile.

简而言之,没有volatile,线程可以缓存变量的值:它没有看到另一个线程设置的新值,没有某种内存屏障。


推荐阅读