线程执行期间的对象状态修改

时间:2016-04-13 16:23:46

标签: java multithreading javafx

我正在使用javafx开发一款小游戏(炸弹人)。基本上,我有玩家可以种植炸弹。炸弹持续时间(例如爆炸前1500毫秒)。

所以,当我的播放器播放炸弹时,我使用Thread.sleep(ms)在炸弹中开始一个线程,然后我通知播放器炸弹爆炸了。

事情是,我的玩家可以放下他的炸弹然后移动......但是当炸弹爆炸时,它会在炸弹播种时用坐标通知玩家的实例...

例如,如果我的玩家在[2; 2]中,植入炸弹,然后移动到[2; 4],然后炸弹爆炸,我的玩家回到[2; 2] ...

任何人都知道如何实现我的炸弹所指向的玩家实例......?

以下是代码示例:

public class Player{
    public void putBomb(){
        listBomb.add(new Bomb(this));
    }

    public void refresh(){
        System.out.println(xCoordinate+" "+yCoordinate);
    }

}

public class Bomb{
    public Bomb(Player p){
        observer=p;

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1500);
                    notify();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }).start();
    }

    public void sendNotification(){
        observer.refresh();
    }

}

2 个答案:

答案 0 :(得分:1)

由于您的问题是特定于JavaFX,因此有关如何执行此操作的建议与非GUI Java程序不同(因为JavaFX具有内置并发协助和单线程应用程序编程模型)。

您不需要其他帖子,您可以使用PauseTransition

public class Bomb{
    public Bomb(final Player player){
        PauseTransition pause = new PauseTransition(Duration.seconds(1.5));
        pause.setOnFinished(event -> player.refresh());
        pause.play();
    }
);

如果由于某种原因您不希望使用转换,并且您想使用自己的线程,那么您应该使用JavaFX concurrency utilitiesTask

如果您不想使用任务,那么您仍然可以创建自己的线程或可运行,但请确保使用Platform.runLater()进行任何回调。例如:

public class Bomb{
    public Bomb(final Player player){
        new Thread(() -> {
                try {
                    Thread.sleep(1500);
                    Platform.runLater(() -> player.refresh());
                } catch (InterruptedException e) {}
            }
        }).start();
    }
}

在不同的方法中,我推荐PauseTransition而不是其他方法,因为您不需要处理容易出错的并发细节,例如线程。

答案 1 :(得分:0)

您的运行方法在[this.]notify()上调用synchronized而不是this。我希望它总是抛出一个IllegalMonitorStateException

此外,如果不设置其他线程可以检查的变量,则调用notify()几乎总是错误的。 notify()的问题在于它根本不做任何事情,除非某个其他线程碰巧在同一个对象的wait()调用中。没有适当的同步,你无法保证这是真的。

只有一种正确的方法可以使用wait()notify(),这是Oracle调用保护块的设计模式。 https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html