2

我正在练习渲染和绘制图形,我似乎无法找出为什么 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)

是我的线程有问题吗?我怎样才能解决这个问题?

这是我的源代码。

起点.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");

            }
        }

    }
}

球.java

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);

    }
}
4

3 回答 3

12

看着

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();
于 2013-07-16T20:19:15.297 回答
9

这是你的问题:

Thread thread = new Thread(this);
thread.start();

b1 = new Ball(40, 40);
b2 = new Ball(70, 200);

您需要在调用之前设置b1--在新线程中调用您的方法的调用,并且有可能在这些变量初始化之前调用 run 方法,从而导致您的 NullPointerException。b2thread.start()startrun


编辑:

为了解决线程问题,考虑一个概念模型非常有用,其中 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块或更高级别的锁之类的语言结构来限制来自不同线程的指令可以交错的方式。

于 2013-07-16T20:19:03.797 回答
3

此错误告诉您 b1 或 b2(或两者)未初始化(即为空)

为什么会出现这种情况需要几分钟的分析,但这是当前的问题。

编辑:查看 Alex 和 Chancea 的帖子。

于 2013-07-16T20:19:02.960 回答