Timer&TimerTaskの深い分析
4313 ワード
Javaでは、一般的なタイミングメカニズム、Timer&TimerTaskがあります.便利に:
1)ある時点で何かをし、public void schedule(TimerTask task,Date when);
2)ある遅延後に何かをし、public void schedule(TimerTask task,long delay);
この2つの方法では、public void schedule(TimerTask task,long delay,long period);public void schedule(TimerTask task, Date when, long period);
くだらないことは言わないで、例を見てみましょう.
Timerは非同期タスクの起動メカニズムを提供していると言える.非同期といえば、ほほほ、マルチスレッドがあるに違いない.ここでは、2つまたは3つのスレッドについて説明します.
1)現在のスレッド,つまりTimerTestでMainメソッドが走るそのスレッドは,これは多く言う必要はなく,すべて知っている.
2)タスクスレッド,すなわちMyTaskスレッド.これも複雑ではありません.TimerTaskの実現を見てみるとわかります.
問題は、このタスクが単独でスレッドを開いたことですか?焦らないで、後に答えがあります.
3)Timerスレッド;
Timer自体は単独でスレッドを開いていますか?はい!Timerのコードを見ればわかります.ポリシー・モード.Timerは特定の機能実装を静的内部クラスTimerImplに委任する.Timerクラスには静的内部クラスTimerImplがあり、Threadが継承されています.次に、このTimerImpleサブスレッドのライフサイクルを分析します.
作成:Timerインスタンスが構築されると、サブスレッドが起動します.では、いつ終わったのでしょうか.実際にはTimerImplを見てみましょうrun()メソッドのwhileループはどのように終了しますか.
a)当Timer.cancel()が呼び出されると、cancelledフラグがtrueに設定され、ループが終了し、スレッドが終了する.
b)あるtaskのrun()メソッドが異常に終了するとcancelledもtrueに設定され、ループが終了し、スレッドが終了する.
以上のコードは、taskを見て、無視されやすい真実を明らかにした.run(); TimerTaskはRunnableインタフェースを実現したが、TimerTaskはstartではなくrun()メソッドを直接実行されていることが分かったのではないでしょうか.したがって,TimerTaskは単独でスレッドを開くのではなく,TimerImplサブスレッドを走っている.このような事実に基づいて、TimeTaskのrun()メソッドで時間がかかりすぎる操作をすることはできません.そうしないと、他のtaskの時間通りの実行に影響を与える可能性があります.
ふふ、おかしいかもしれませんが、Runnableはマルチスレッドメカニズムのために準備されているのではないでしょうか.はい、Runnableは主にマルチスレッドメカニズムのために準備されていますが、必ずしもそうではありません.定義と注釈を見てみましょう.
一番上の行の注釈が見えますね.通常は別のスレッドで実行されますが、必ずしも(always)ではありません.したがって,このrunは必ずしも別のスレッドを走っているとは限らない.実は、Runnableのこのような別のように見える使い方も、よく使われています.
c)TimerTaskキューが空である、TimerImple.finishedフラグはtrueに設定されます.このマークはいつtrueに置かれたのか、この問題は面白い.Timerのもう一つの静的内部クラスを見てみましょう.
FinalizerHelperの例、すなわちTimerのプライベートメンバー変数(finalizer)がGCされたとき、FinalizerHelper.finalize()メソッドはJVMによって呼び出され、TimerImple.finishedフラグはtrueに設定されます.見えるよティマーfinalizerは引用されていないので、最も早くGCに落とされたはずです.これは光栄な使命を果たすことができることを保証しています~~~~~~~~~TimerImplスレッドを殺すのを助けることができます.
TimerによるTaskの管理
TimerImpleではTaskの具体的な管理操作を独自の内部クラスTimerHeapに委任した.TimerHeap内部に動的に拡張可能なTimerTask配列が定義されており、この配列はタスクキューを実現し、早期に実行されるタスクほど前に並べられている.
1)ある時点で何かをし、public void schedule(TimerTask task,Date when);
2)ある遅延後に何かをし、public void schedule(TimerTask task,long delay);
この2つの方法では、public void schedule(TimerTask task,long delay,long period);public void schedule(TimerTask task, Date when, long period);
くだらないことは言わないで、例を見てみましょう.
import java.io.IOException;
import java.util.Timer;
public class TimerTest {
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new MyTask(), 1000, 2000); // 1 , 2 , Data , .
while(true) {
try {
int ch = System.in.read();
if(ch-'c'==0) {
timer.cancel(); //
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
static class MyTask extends java.util.TimerTask { //
@Override
public void run() {
// accomplish your task here
}
}
Timerは非同期タスクの起動メカニズムを提供していると言える.非同期といえば、ほほほ、マルチスレッドがあるに違いない.ここでは、2つまたは3つのスレッドについて説明します.
1)現在のスレッド,つまりTimerTestでMainメソッドが走るそのスレッドは,これは多く言う必要はなく,すべて知っている.
2)タスクスレッド,すなわちMyTaskスレッド.これも複雑ではありません.TimerTaskの実現を見てみるとわかります.
public abstract class TimerTask implements Runnable {
***
***
public abstract void run();
}
問題は、このタスクが単独でスレッドを開いたことですか?焦らないで、後に答えがあります.
3)Timerスレッド;
Timer自体は単独でスレッドを開いていますか?はい!Timerのコードを見ればわかります.ポリシー・モード.Timerは特定の機能実装を静的内部クラスTimerImplに委任する.Timerクラスには静的内部クラスTimerImplがあり、Threadが継承されています.次に、このTimerImpleサブスレッドのライフサイクルを分析します.
作成:Timerインスタンスが構築されると、サブスレッドが起動します.では、いつ終わったのでしょうか.実際にはTimerImplを見てみましょうrun()メソッドのwhileループはどのように終了しますか.
a)当Timer.cancel()が呼び出されると、cancelledフラグがtrueに設定され、ループが終了し、スレッドが終了する.
b)あるtaskのrun()メソッドが異常に終了するとcancelledもtrueに設定され、ループが終了し、スレッドが終了する.
try {
task.run();
taskCompletedNormally = true;
} finally {
if (!taskCompletedNormally) {
synchronized (this) {
cancelled = true;
}
}
}
以上のコードは、taskを見て、無視されやすい真実を明らかにした.run(); TimerTaskはRunnableインタフェースを実現したが、TimerTaskはstartではなくrun()メソッドを直接実行されていることが分かったのではないでしょうか.したがって,TimerTaskは単独でスレッドを開くのではなく,TimerImplサブスレッドを走っている.このような事実に基づいて、TimeTaskのrun()メソッドで時間がかかりすぎる操作をすることはできません.そうしないと、他のtaskの時間通りの実行に影響を与える可能性があります.
ふふ、おかしいかもしれませんが、Runnableはマルチスレッドメカニズムのために準備されているのではないでしょうか.はい、Runnableは主にマルチスレッドメカニズムのために準備されていますが、必ずしもそうではありません.定義と注釈を見てみましょう.
/**
* Represents a command that can be executed. Often used to run code in a
* different {@link Thread}.
*/
public interface Runnable {
/**
* Starts executing the active part of the class' code. This method is
* called when a thread is started that has been created with a class which
* implements {@code Runnable}.
*/
public void run();
}
一番上の行の注釈が見えますね.通常は別のスレッドで実行されますが、必ずしも(always)ではありません.したがって,このrunは必ずしも別のスレッドを走っているとは限らない.実は、Runnableのこのような別のように見える使い方も、よく使われています.
c)TimerTaskキューが空である、TimerImple.finishedフラグはtrueに設定されます.このマークはいつtrueに置かれたのか、この問題は面白い.Timerのもう一つの静的内部クラスを見てみましょう.
private static final class FinalizerHelper {
private final TimerImpl impl;
FinalizerHelper(TimerImpl impl) {
this.impl = impl;
}
@Override protected void finalize() throws Throwable {
try {
synchronized (impl) {
impl.finished = true;
impl.notify();
}
} finally {
super.finalize();
}
}
}
FinalizerHelperの例、すなわちTimerのプライベートメンバー変数(finalizer)がGCされたとき、FinalizerHelper.finalize()メソッドはJVMによって呼び出され、TimerImple.finishedフラグはtrueに設定されます.見えるよティマーfinalizerは引用されていないので、最も早くGCに落とされたはずです.これは光栄な使命を果たすことができることを保証しています~~~~~~~~~TimerImplスレッドを殺すのを助けることができます.
TimerによるTaskの管理
TimerImpleではTaskの具体的な管理操作を独自の内部クラスTimerHeapに委任した.TimerHeap内部に動的に拡張可能なTimerTask配列が定義されており、この配列はタスクキューを実現し、早期に実行されるタスクほど前に並べられている.