メソッド内にローカルスレッドを宣言するとどうなりますか?通常、すべてのローカル変数は、スタックにすべて割り当てられているので、関数が返るとすぐになくなります。しかし、ローカルスレッドは別の話になるようです。そうですか?スレッドでのメモリ割り当て
public int A() {
Thread t = new Thread() {
doSomething();
}
t.start();
return -1;
}
メソッド内にローカルスレッドを宣言するとどうなりますか?通常、すべてのローカル変数は、スタックにすべて割り当てられているので、関数が返るとすぐになくなります。しかし、ローカルスレッドは別の話になるようです。そうですか?スレッドでのメモリ割り当て
public int A() {
Thread t = new Thread() {
doSomething();
}
t.start();
return -1;
}
スレッドは独自のGCルートです。したがって、作成コンテキストにもかかわらずスレッドを作成するたびに、runメソッドが完了するまではGCへの準備ができません。これは、ローカルメソッドが完了し、スレッドがまだ生きていても当てはまります。
例:メソッドをエスケープしていなかった何も定義されたが、その後、GC用にマークされて
public void doSomeAsync(){
Thread th = new Thread(new Runnable(){
public void run(){
Thread.sleep(500);
}
});
th.start();
//do something else quickly
}
//do somethign else quickly
後。スレッドthはGC用にマークされず、ヒープ上に正しくスレッドスタックされて配置されます。
スレッドはローカルコンテキストから開始された場合は、スレッドがRunnableのrun
メソッドが実行を完了したのですまで実行を継続します。
メソッド内にローカルThread
をスポーンする場合、Thread
が完了するまでfinal
と宣言されたローカルメソッド変数のみが固執します。 Thread
がrun()
メソッドを完了すると、スレッドとそれを作成したメソッドから利用可能な最終変数は、他のすべてと同様にガベージコレクションされます。元のメソッドと生成されたスレッドのrun()
メソッド内で使用
明確化
のみfinal
変数は、メソッドとrun()
方法の両方が完了するまでゴミが収集されてから控えます。スレッドが変数にアクセスしない場合、スレッドの存在は、元のメソッドが完了した後に変数がガベージコレクションされるのを妨げません。
参照
http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html
が、スタックまたはヒープ上のローカルスレッドですか? – peter
ファイナルは、フィールドが「つぶれている」かどうかは関係ありません。ファイナルは、フィールドを再割り当てできるかどうかに影響し、コンストラクタの割り当て順序にも影響します。 – Gray
それは確かです。メソッドの先頭に最終変数を宣言するメソッドがある場合、run()メソッド内でその最終変数にアクセスするスレッドが生成され、スレッドがまだ実行されている限り、最終変数はガベージコレクションされません。なぜなら、その最終変数はスレッドによってJVMのオブジェクトグラフに到達可能であるからです。これは、スレッドを生成した元のメソッドがrun()メソッドの前に戻るかどうかにかかわらず、trueです。 – CodeBlind
変数がプリミティブである場合、それはスタック上になるだろうとメソッドが返すときに消えてしまいます - しかし、あなたのスレッドのRunnable
インスタンス(またはものは何でもスレッドの肉を含んでいる)はそのプリミティブ値のコピーを持ちます。
変数が参照型である場合、オブジェクトはヒープ上に割り当てられ、参照がなくなるまで生き残ります。その時点でガベージコレクションの対象となります。そのオブジェクトへの参照はスタック上にあり、メソッドが戻るときにはなくなりますが、プリミティブと同様に、スレッドのRunnable
はその同じ参照のコピーを持ちます(したがってそのオブジェクトは生き続けるでしょう)。
ジョンの答えは良いですが、私はもう少し詳しく説明したいと思いました。
public void startThread() {
long var1 = 10;
byte[] var2 = new byte[1024];
final byte[] var3 = new byte[1024];
final byte[] var4 = new byte[1024];
Thread thread = new Thread(new Runnable() {
private long var5 = 10;
private byte[] var6 = new byte[1024];
public void run() {
int var7 = 100;
byte[] var8 = new byte[1024];
System.out.println("Size of var4 is " + var4.length);
baz();
...
}
private void baz() {
long var9 = 2;
byte[] var10 = new byte[1024];
...
}
});
thread.start();
}
ここでスレッドの周りに割り当てられた変数がいくつかあります。また、Thread
オブジェクトと、スレッドが実行されているRunnable
ターゲットがあります。
startThread()
にローカルになりそうだが、関連するThread
もJVMによって管理されています。 run()
メソッドが終了し、Thread
がJVMによって取得された後にのみGCされます。 Thread
がGC'dの後に、Thread
によって使用されるすべてのフィールドはGC'dになります。Thread
の処理が完了した後にGCしてGCすることができます。startThread()
にローカルであり、スタックに割り当てられています。 startThread()
メソッドが終了し、スタックが再利用されると上書きされます。startThread()
にローカルであり、ヒープに割り当てられます。 final
ではないため、スレッドで使用することはできません。 startThread()
の終了後にGCすることができます。startThread()
にローカルであり、ヒープに割り当てられます。これはfinal
ですので、はスレッドで使用できますが、そうではありません。 startThread()
の終了後にGCすることができます。startThread()
にローカルであり、ヒープに割り当てられます。これはfinal
であり、スレッドによって使用されます。 startThread()
のメソッドが終了した後にのみGCすることができます。とRunnable
とThread
はGCです。Runnable
のローカルフィールドで、匿名クラスRunnable
の一部としてヒープに割り当てられます。 Runnable
の終了後にGCし、Runnable
とThread
をGCすることができます。Runnable
の内部のローカルフィールドであり、ヒープに割り当てられます。 Runnable
の終了後にGCし、Runnable
とThread
をGCすることができます。run()
メソッドの内部のローカルフィールドで、新しいスレッドのスタックに割り当てられます。 run()
メソッドが終了し、スタックが再利用されると上書きされます。run()
メソッド内のローカルフィールドであり、ヒープに割り当てられます。 run()
メソッドの終了後にGCすることができます。baz()
メソッドの内部のローカルフィールドであり、新しいスレッドのスタックに割り当てられます。 baz()
メソッドが終了し、スタックが再利用されると上書きされます。baz()
メソッド内のローカルフィールドであり、ヒープに割り当てられます。 baz()
メソッドの終了後にGCすることができます。カップルその他の注意事項:
startThread()
終了後GC'dすることができます開始されることはありません場合。 Runnable
と、それに関連するすべての変数は、同様にGCすることができます。startThread()
で宣言されたfinal long varX
プリミティブがスレッドで使用されている場合は、ヒープに割り当てられ、ではなく、スタックに割り当てられている必要があります。startThread()
が終了すると、まだ使用されます。
この質問は読みにくい/理解しています。それを肉体に編集できますか?あなたが求めていることをよりよく説明してください。簡潔に表示してください。コードサンプル? – Gray