Java 这个演示5次中有4次有效,为什么它有时会给我一个错误?
我正在练习渲染和绘制图形,我似乎不明白为什么eclipse会在大约1/5的时间内给我一个错误Java 这个演示5次中有4次有效,为什么它有时会给我一个错误?,java,applet,awt,event-dispatch-thread,thread-sleep,Java,Applet,Awt,Event Dispatch Thread,Thread Sleep,我正在练习渲染和绘制图形,我似乎不明白为什么eclipse会在大约1/5的时间内给我一个错误 Exception in thread "Thread-3" java.lang.NullPointerException at game.StartingPoint.run(StartingPoint.java:74) at java.lang.Thread.run(Unknown Source) 我的线程有问题吗?我怎样才能解决这个问题 这是我的源代码 StartingPoint.java
Exception in thread "Thread-3" java.lang.NullPointerException
at game.StartingPoint.run(StartingPoint.java:74)
at java.lang.Thread.run(Unknown Source)
我的线程有问题吗?我怎样才能解决这个问题
这是我的源代码
StartingPoint.java:
package game;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
public class StartingPoint extends Applet implements Runnable {
Image i;
Graphics doubleG;
Ball b1;
Ball b2;
public StartingPoint() {
}
@Override
public void init() {
}
@Override
public void start() {
setSize(480, 360);
Thread thread = new Thread(this);
thread.start();
b1 = new Ball(40, 40);
b2 = new Ball(70, 200);
}
@Override
public void stop() {
}
@Override
public void destroy() {
}
@Override
public void update(Graphics g) {
if (i == null) {
i = createImage(this.getWidth(), this.getHeight());
doubleG = i.getGraphics();
}
doubleG.setColor(getBackground());
doubleG.fillRect(0, 0, this.getWidth(), this.getHeight());
doubleG.setColor(getForeground());
paint(doubleG);
g.drawImage(i, 0, 0, this);
}
@Override
public void paint(Graphics g) {
b1.paint(g);
b2.paint(g);
}
@Override
public void run() {
while (true) {
b1.update(this);
b2.update(this);
repaint();
try {
Thread.sleep(30);
} catch (Exception e) {
System.out.print("Error");
}
}
}
}
package game;
import java.awt.Color;
import java.awt.Graphics;
public class Ball {
double gravity = 15.0;
double energyLoss = .65;
double outsideEnergy = .95;
double dt = .25;
double xFriction = .9;
int x = 40;
int y = 40;
double dx = 7.0;
double dy = 0.0;
int radius = 20;
public Ball() {
}
public Ball(int x, int y) {
this.x = x;
this.y = y;
}
public void update(StartingPoint sp) {
if (x <= 0 | x >= sp.getWidth()) {
dx = -dx;
}
if (y > sp.getHeight() - radius - 1) {
y = sp.getHeight() - radius - 1;
dy *= energyLoss;
dy = -dy;
dx *= outsideEnergy;
} else {
// velocity
dy = dy + gravity * dt;
// d=viT + 1/2(a)t^2
y += dy * dt + .5 * gravity * dt * dt;
}
x += dx;
}
public void paint(Graphics g) {
g.setColor(Color.green);
g.fillOval(x - radius, y - radius, radius * 2, radius * 2);
}
}
Ball.java:
package game;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
public class StartingPoint extends Applet implements Runnable {
Image i;
Graphics doubleG;
Ball b1;
Ball b2;
public StartingPoint() {
}
@Override
public void init() {
}
@Override
public void start() {
setSize(480, 360);
Thread thread = new Thread(this);
thread.start();
b1 = new Ball(40, 40);
b2 = new Ball(70, 200);
}
@Override
public void stop() {
}
@Override
public void destroy() {
}
@Override
public void update(Graphics g) {
if (i == null) {
i = createImage(this.getWidth(), this.getHeight());
doubleG = i.getGraphics();
}
doubleG.setColor(getBackground());
doubleG.fillRect(0, 0, this.getWidth(), this.getHeight());
doubleG.setColor(getForeground());
paint(doubleG);
g.drawImage(i, 0, 0, this);
}
@Override
public void paint(Graphics g) {
b1.paint(g);
b2.paint(g);
}
@Override
public void run() {
while (true) {
b1.update(this);
b2.update(this);
repaint();
try {
Thread.sleep(30);
} catch (Exception e) {
System.out.print("Error");
}
}
}
}
package game;
import java.awt.Color;
import java.awt.Graphics;
public class Ball {
double gravity = 15.0;
double energyLoss = .65;
double outsideEnergy = .95;
double dt = .25;
double xFriction = .9;
int x = 40;
int y = 40;
double dx = 7.0;
double dy = 0.0;
int radius = 20;
public Ball() {
}
public Ball(int x, int y) {
this.x = x;
this.y = y;
}
public void update(StartingPoint sp) {
if (x <= 0 | x >= sp.getWidth()) {
dx = -dx;
}
if (y > sp.getHeight() - radius - 1) {
y = sp.getHeight() - radius - 1;
dy *= energyLoss;
dy = -dy;
dx *= outsideEnergy;
} else {
// velocity
dy = dy + gravity * dt;
// d=viT + 1/2(a)t^2
y += dy * dt + .5 * gravity * dt * dt;
}
x += dx;
}
public void paint(Graphics g) {
g.setColor(Color.green);
g.fillOval(x - radius, y - radius, radius * 2, radius * 2);
}
}
打包游戏;
导入java.awt.Color;
导入java.awt.Graphics;
公共班级舞会{
双重重力=15.0;
双能量损耗=0.65;
双外能量=.95;
双dt=0.25;
双X摩擦=.9;
int x=40;
int y=40;
双dx=7.0;
双dy=0.0;
int半径=20;
公共舞会{
}
公共球(整数x,整数y){
这个.x=x;
这个。y=y;
}
公共作废更新(StartingPoint sp){
如果(x=sp.getWidth()){
dx=-dx;
}
如果(y>sp.getHeight()-radius-1){
y=sp.getHeight()-半径-1;
dy*=无能量;
dy=-dy;
dx*=外部能量;
}否则{
//速度
dy=dy+重力*dt;
//d=viT+1/2(a)t^2
y+=dy*dt+.5*重力*dt*dt;
}
x+=dx;
}
公共空间涂料(图g){
g、 setColor(Color.green);
g、 圆角(x-半径,y-半径,半径*2,半径*2);
}
}
此错误告诉您b1或b2(或两者)未初始化(即为空)
为什么会出现这种情况需要几分钟的分析,但这是当前的问题
编辑:查看Alex和Chancea的帖子。这是你的问题:
Thread thread = new Thread(this);
thread.start();
b1 = new Ball(40, 40);
b2 = new Ball(70, 200);
在调用thread.start()
之前,您需要设置b1
和b2
——调用start
在新线程中调用run
方法,并且有可能在初始化这些变量之前调用run方法,从而导致NullPointerException
编辑:
为了解决线程问题,考虑JVM一次只能执行一行代码的概念模型是有用的,只要来自任何一个线程的代码行以正确的顺序执行,不同线程的不同代码行可以以任意顺序交织。对于现代CPU架构,事实并非如此,只是假装
当您在多线程代码中遇到问题时,您的目标是找到一种交叉操作的方法来重现您的问题。例如: Thread 1 Thread2
1 b1 = null; (implicit in constructor)
2 b2 = null; (implicit in constructor)
3 Thread thread = new Thread(this)
4 thread.start();
5 b1 = new Ball(40, 40);
6 b1.update(this); (OK because b1 is initialized)
7 b2.update(this); (NPE - b2 is not initialize)
8 b2 = new Ball(70, 200);
然后,您的目标是重新排列同一线程中的行,以确保不会发生有问题的序列,或者使用诸如synchronized
块或更高级别的锁之类的语言构造来限制来自不同线程的指令可以交错的方式。查看
Thread thread = new Thread(this);
thread.start();
b1 = new Ball(40, 40);
b2 = new Ball(70, 200);
线程启动后,您正在初始化变量。有时线程在实际初始化它们之前使用它们,有时首先初始化它们。在调用start()
之前移动它们:
b1 = new Ball(40, 40);
b2 = new Ball(70, 200);
Thread thread = new Thread(this);
thread.start();
关键词是
Thread
和null
。很可能有人认为某些东西是“非线程安全的”。这并不是真正回答你的问题,但我觉得应该提到它。你似乎理解了一些基本的物理原理,并在这里正确地应用了它们,那么为什么不利用向量呢?它将有助于在加速方面对函数进行更多的分类。您可以创建一个恒定的重力向量,并可以连续应用它。只要考虑一下: