2016-08-30 4 views
9

私は、ユーザの操作でメッセージをスプラッシュするためのタイマーを起動するアプリケーションを持っています。 JDKのプロファイラでは、他のすべてのスレッドはGC(私が推測する)の実行後に削除されているようだが、作成されたタイマーは削除されていない。何が起こっているのでしょうか?Java - 実行後にタイマが削除されない

私のタイマー:

/** 
* @param owner 
* @param added 
*/ 
public static void splashParentWithAnimation(AnchorPane owner, Parent added,double posX,double posY) { 
    // addParentWithAnimation(owner, added); 
    owner.getChildren().add(added); 

    AnchorPane.setLeftAnchor(added, posX); 

    AnchorPane.setTopAnchor(added, posY); 

    FadeTransition ft1 = new FadeTransition(Duration.millis(300), added); 
    ft1.setFromValue(0.0); 
    ft1.setToValue(1.0); 
    ft1.play(); 


    Timer messagePrinter = new Timer(); 
    messagePrinter.schedule(new TimerTask() { 

     @Override 
     public void run() { 
      Platform.runLater(() -> { 

       if (!owner.getChildren().contains(added)) 
        return; 

       FadeTransition ft1 = new FadeTransition(Duration.millis(300), added); 
       ft1.setFromValue(1.0); 
       ft1.setToValue(0.0); 
       ft1.play(); 
       ft1.setOnFinished((e) -> { 

        if (owner.getChildren().contains(added)) 
         owner.getChildren().remove(added); 
       }); 

      }); 

     } 
    }, 1000); 
} 

JDKプロファイラ: enter image description here

それは私が静的メソッドを使用していますか、私はそれを自分自身を破壊する必要があるためですか?

答えて

7

実際には、ここではタイマー終了に問題はありません。プロファイラに表示されているスレッドはすでに終了しています–左側に白いボックスがあり、それらが死んでいることを示しています。

プロファイラは、プログラム実行中に作成されたすべてのスレッドを表示します。スレッドがすでに停止してガベージコレクトされている場合でも同様です。

ラムダの代わりに、TimerTaskというサブクラスを作成し、同じことを行い、何かを印刷するfinalize()メソッドを再定義することができます。ガベージコレクションが実行されると、タスクが確定されます。スレッドが停止するのは、RunnableTimerTaskが実装されている)への参照をドロップするThreadクラス内の唯一の場所であるためです。

もう1つの方法は、テーブルの上にある[表示]ドロップダウンリストから[ライブスレッド]を選択することです。

さらに、Timerをより良いものに置き換えることをお勧めします。いくつかのタスクを遅らせる必要があるたびにスレッドを作成するのは無駄です。 ScheduledThreadPoolExecutorを見て、あなたの仕事のためにはるかに適切と思われる:

// Create a shared executor with a single thread 
private final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1); 

// Instead of creating a Timer, schedule the task 
executor.schedule(() -> { 
    // Do what you need here 
}, 1, TimeUnit.SECONDS); 

// Don't forget to terminate the scheduler when you don't need it anymore 
scheduler.terminate(); 

一度にあまりにも多くのスケジュールタスクを持っており、これらのタスクは十分に小さくない場合は、エグゼキュータに複数のスレッドを追加することができます。

+0

私はそれについてはわかりませんが、とにかく知っておいて、私はjavaFXのタイムラインを使用しました(少なくとも私のために)より良いです –

2

これは、手動でタイマーを処理する必要があるためです。

java.util.Timerを使用する場合は、リソースを解放するためにcancelメソッドに電話する必要があります。

+0

どうすればいいですか? –

+0

name_of_timer.cancel(); ? –

+0

はい。この場合、 'messagePrinter.cancel();' – talex

1

タイマーは非デーモンスレッドで作成されます。非デーモンスレッドは、プログラムの終了をブロックする可能性があります。デーモンスレッドを使用するTimerのコンストラクタを使用する必要があります。

boolean daemon=true; Timer messagePrinter = new Timer(daemon);

しかしAndrew Lyginが示唆ように私はExecutorServiceのを使用しています。

関連する問題