睡眠と待機の違いを自分の目で確かめたかった。
待機は、監視ロックの所有権を解放するため、同期ブロックでのみ実行できます。スリープはモニター ロックとは関係ありませんが、既にモニター ロックの所有者であるスレッドは、スリープしている場合でもその所有権を失うべきではありません。
そのために私はテストをしました:
手順:
- 同期ブロックで 5 秒間待機するスレッドを開始しました。
- 3 秒待機し、モニター ロックを取得する別のスレッドを開始し (スレッド A が待機しているため)、モニター ロックを保持したまま 5 秒間スリープします。
期待される結果: スレッド - A は 8 秒後にのみロックを再取得し、スレッド - B は同期ブロックを終了してモニター ロックを最終的に解放します。
実結果。スレッド - A は 5 秒後にモニター ロックを取得します。
ここで何が起こったのか説明してもらえますか?
public static void main(String[] args) {
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("r1 before synch block");
synchronized (this) {
System.out.println("r1 entered synch block");
try {
wait(5000);
System.out.println("r1 finished waiting");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Runnable r2 = new Runnable() {
@Override
public void run() {
System.out.println("r2 before synch block");
synchronized (this) {
System.out.println("r2 entered synch block");
try {
Thread.currentThread();
Thread.sleep(5000);
//wait(5000);
System.out.println("r2 finished waiting");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
try {
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
Thread.currentThread();
Thread.sleep(3000);
t2.start();
t1.join();
t2.join();
System.out.println(Thread.currentThread().getName() + " Finished joining");
} catch (Exception e) {
e.printStackTrace();
}
}
編集:
OK、エラーを理解しました-これを待っています-r1/r2であり、同じオブジェクトではありません。
今、私はそれを変更し、両方が同じオブジェクトを取得しました - メインのクラスインスタンス。1. r1 は Main.this のモニター ロックの所有権を取得します。 2. r1 はそれを解放します。3. r1 が再取得しようとすると、例外が発生します。
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at Main$1.run(Main.java:28)
at java.lang.Thread.run(Unknown Source)
on synchronized (Main.this)
ここで何が問題なのですか?
public static void main(String[] args) {
Main main = new Main();
main.test();
}
public void test() {
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("r1 before synch block");
synchronized (Main.this) {
System.out.println("r1 entered synch block");
try {
wait(5000);
System.out.println("r1 finished waiting");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Runnable r2 = new Runnable() {
@Override
public void run() {
System.out.println("r2 before synch block");
synchronized (Main.this) {
System.out.println("r2 entered synch block");
try {
Thread.currentThread();
Thread.sleep(5000);
//wait(5000);
System.out.println("r2 finished waiting");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
try {
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
Thread.currentThread();
Thread.sleep(3000);
t2.start();
t1.join();
t2.join();
System.out.println(Thread.currentThread().getName() + " Finished joining");
} catch (Exception e) {
e.printStackTrace();
}
}