2016-04-13 21 views
0

javafx kullanarak küçük bir oyun (bomberman) üzerinde çalışıyorum. Temel olarak, bomba atabilecek oyuncularım var. Bombanın bir süresi vardır (örneğin, patlamadan 1500ms).İş parçacığı yürütme sırasında nesne durum değişikliği

Oyuncum bir bomba attığında, bir Thread.sleep (ms) kullanarak, bombada bir iş parçacığı başlatıyorum ve oyuncunun bombayı patlattığını bildirdikten hemen sonra.

Şey benim oyuncu bomba sonra hareket bırakabilirsiniz olduğunu ... Ama bomba patlar, bu koordinat ile oyuncunun örneğini bildirmek zaman bomba eğer Örneğin

... dikilmiş iken benim oyuncum [2; 2], bir bomba atıyor, sonra [2; 4] 'e geçiyor, bomba patlıyor, oyuncum [2; 2]' ye geri dönüyor ...

Herkes nasıl olabilir? bombamın işaret ettiği oyuncunun örneğini hayata geçirelim ...? Sorunuza olarak

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

} 
+0

notify Nesne sınıfında son yerel bir yöntemdir, bunu sınıfınızda bildiremezsiniz ... – AdamSkywalker

+0

sorgunuz hakkında - senkronize edilmiş olarak yenileme bildirebilir, bu sizin görünürlük sorunları giderir – AdamSkywalker

+0

Aslında yöntem değil "bildir" denir, sadece basitleştirdim. Senkronize kullanımı, herhangi bir şeyi talihsiz bir şekilde değiştirmez. – IronRabbit

cevap

1

özgü, bu (olmayan GUI Java programından farklılık JavaFX dahili çünkü eşzamanlılık yardımı nasıl yapılacağına ilişkin tavsiyeler ve JavaFX: İşte

kod örneği verilmiştir tek iş parçacıklı uygulama programlama modeli).

Başka bir iş parçacığına ihtiyacınız yoktur, bir PauseTransition kullanabilirsiniz. Herhangi bir nedenle bir geçiş kullanmak istemediğini ve kendi diş kullanmak istiyorsanız

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

, o zaman JavaFX concurrency utilities böyle Task olarak kullanmak görünmelidir.

Bir Görev kullanmak istemiyorsanız, yine de kendi iş parçacığınızı veya runnable'ı oluşturabilir, ancak herhangi bir geriçağırımın Platform.runLater() kullanarak yapıldığından emin olun. Örneğin: o zaman yanlış almak kolay olan bu tür diş olarak eşzamanlılık ayrıntılar ile uğraşmak gerekmez gibi farklı yaklaşımlar Of

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

, ben diğerlerine PauseTransition öneriyoruz.

0

Çalıştırma yönteminiz, numaralı telefondan synchronized olmadan [this.]notify() numaralarını çağırır. Her zaman bir IllegalMonitorStateException atmasını beklerdim.

Ayrıca, diğer iş parçacıklarının inceleyebileceği bazı değişkenleri ayarlamadan, notify() numaralı telefonu aramak neredeyse her zaman bir hatadır. Aynı nesne için wait() numaralı çağrıda başka bir iş parçacığının olmaması durumunda, numaralı sorun, 'un hiçbir şey yapmamasıdır. Uygun senkronizasyon olmadan, bunun doğru olacağını garanti etmenin hiçbir yolu yoktur.

Orada wait() ve notify() kullanan tek doğru yol var, o da Oracle bir korunan blok çağıran bir tasarım modelinde bulunuyor.

İlgili konular