0

I'm working on a JavaFx application. The application creates multiple threads(same class). The threads are created here:

for (i = 0; i < turtlesNumber; i++) {
        TurtleRunThread turtleRunThread = new TurtleRunThread();

        turtleRunThread.setController(this.controller);
        turtleRunThread.setTurtle(this.model.getTurtles().get(i));
        turtleRunThread.setFinish(this.mainUI.getRacePane().getWidth() - 47.3);

        turtleRunThread.start();

        threadArrayList.add(turtleRunThread);
    }

This is the run method of the thread class:

     public void run() {
    //this.controller.run(this.turtle, this.finish);

    long speed = 500;
    double step = 20; //10 pixeli

    while (turtle.getX() < finish) {
        Random random = new Random();

        controller.modifyTurtlePosition(turtle, speed, step);

        if (Math.random() < 0.2) {
            if (Math.random() < 0.5) {
                if (speed > 100)
                    speed -= random.nextLong() % (((double)1 / 3) * speed);
            } else {
                if (speed < 1500)
                    speed += random.nextLong() % (((double)1 / 3) * speed);
            }
        }
    }
}

And this is the controller method "modifyTurtlePositions(...)":

    public void modifyTurtlePosition(final ImageView turtle, long speed, double step) {
    Timeline timeline = new Timeline();

    final double newX = turtle.getX() + step;

    KeyValue keyValue = new KeyValue(turtle.xProperty(), turtle.getX() + step);
    KeyFrame keyFrame = new KeyFrame(Duration.millis(speed), keyValue);

    timeline.getKeyFrames().add(keyFrame);

    timeline.setOnFinished(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent actionEvent) {
            turtle.setX(newX);
        }
    });

    timeline.play();

    try {
        Thread.sleep(speed);
    } catch (InterruptedException e) {
        System.err.println(e.getMessage());
    }
}

The problem is that if I don't make this method synchronized I get the following exception:

Exception in thread "Thread-16" java.lang.ArrayIndexOutOfBoundsException: 2
at java.util.ArrayList.add(ArrayList.java:412)
at com.sun.scenario.animation.AbstractMasterTimer.addPulseReceiver(AbstractMasterTimer.java:211)
at com.sun.scenario.animation.shared.AnimationPulseReceiver.addPulseReceiver(AnimationPulseReceiver.java:70)
at com.sun.scenario.animation.shared.AnimationPulseReceiver.start(AnimationPulseReceiver.java:84)
at javafx.animation.Animation.play(Animation.java:775)
at javafx.animation.Animation.play(Animation.java:762)
at sample.Controller.modifyTurtlePosition(Controller.java:95)
at sample.TurtleRunThread.run(TurtleRunThread.java:35)
    java.lang.NullPointerException
at     com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(AbstractMasterTimer.java:366)
at com.sun.scenario.animation.AbstractMasterTimer$MainLoop.run(AbstractMasterTimer.java:289)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:456)
at com.sun.javafx.tk.quantum.QuantumToolkit$9.run(QuantumToolkit.java:329)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29)
at com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:73)
at java.lang.Thread.run(Thread.java:722)

Do you have any idea?

1 Answer 1

4

wrap controller.modifyTurtlePosition(turtle, speed, step); into Platform.runLater():

Platform.runLater(new Runnable() {
    public void run() {
        controller.modifyTurtlePosition(turtle, speed, step);
    }
}

All UI operations must be done on UI thread.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.