Java がメモリ グラフからマルチスレッドを実行する方法を理解する
1. メモリグラフの概要
ご存知のとおり、Java クラスのメンバー変数はメソッド領域に保存され、Java ランタイム メソッドはスタックに保存され、メソッド内のローカル変数もスタックに保存され、参照型 (新しいオブジェクト) はヒープ メモリに保存されます。以下では、Java メモリ内のメソッド領域、スタック メモリ、およびヒープ メモリを使用して、Java メソッドの実行プロセスを示します。
まず Person クラスを定義します。
public class Person {
public int age;
public String name;
public void m1() {
}
public void m2() {
m3();
}
public void m3() {
}
public static void m4() {
}
}
この時点でのメモリマップは次のようになります。
別のテストクラスを定義する
public class Test {
public static void main(String[] args) throws Exception{
Person person1 = new Person();
person1.m1();
}
}
この時点でのメモリマップは次のようになります。
2. シングルスレッドコード実行モード
Test クラスを開始した後、メイン スレッド スタックを作成し、person1 オブジェクトを作成します (ヒープ メモリに格納され、クラス内の非静的メンバーのみを保持します)。
次に、person1 オブジェクトが m1 メソッドを呼び出し、メインスレッド スタックがヒープ メモリ内の person1 オブジェクトのアドレスから m1 メソッドのコピーをコピーし、スタックにプッシュします。
m1 が実行されると、m1 メソッドがスタックからポップアウトされ、メインスレッド全体の内容が終了し、メソッドが 1 つずつスタックからポップアウトされ、作成されたオブジェクト参照が破棄されます。
ヒープ メモリ内の person1 オブジェクトは、他の場所で参照されていない場合、リサイクルされます。
mainメソッドが実行される
3. マルチスレッドコード実行モード
複数のスレッドが参加できるように Test クラスを調整する
public class Test {
public static void main(String[] args) throws Exception{
Thread thread1 = new Thread() {
@Override
public void run() {
Person person1 = new Person();
person1.m2();
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
Person person1 = new Person();
person1.m3();
}
};
// -----------------------
thread1.start();
thread2.start();
Person person1 = new Person();
person1.m1();
}
}
分割線まで実行した場合のメモリマップは以下の通り
次に、start メソッドを実行して、スレッドを準備完了キューにスローします。
スレッド 1 と 2 は両方とも準備完了状態になるため。CPU は実行のためにいつでもタイム スライスを割り当てる可能性があるため、スレッド 1 とスレッド 2 での person1 の作成と、メイン スレッドでの person1 オブジェクトの作成の順序を決定することはできません。メソッドがリサイクルされた後にメインスレッドの person1 のオブジェクトが実行されたか、スレッド 1 とスレッド 2 の作成が開始されたか、または 3 つの person1 オブジェクトが同時に存在している可能性があります。