java - 线程类方法运行内部无限循环
问题描述
我有一个用线程运行的小动画。我用两个按钮暂停和播放动画。这是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){}
}
}
解决方案
你没有显示所有你的代码,但我想它exitFlag
没有被标记为volatile
.
简而言之,没有volatile
,线程可以缓存变量的值:它没有看到另一个线程设置的新值,没有某种内存屏障。
推荐阅读
- c++ - 如何正确链接 cuda 和 cpp 文件之间创建的函数?
- jquery - 根据值更改表列颜色在剃须刀文件中使用 jquery 不起作用
- django - Django 测试有时会失败,有时会成功,可能的原因是什么?
- php - 如果单元格中的值重复,PHP会合并几行
- javascript - 移动版的下拉导航栏不会掉
- javascript - 将数组合并和相乘成一个数组
- swiftui - SwiftUI TextField 可触摸区域
- javascript - 如何在节点 js 中使用 SFTP 限制下载速度
- c# - 无法使用 NCryptExportKey 和 NCryptImportKey 重新导入私钥
- c# - 盒子对撞机没有在玩家的所有轴上记录碰撞