wait,notifyとnotifyallが注意すべき問題
waitを使用すると、notifyとnotifyallがjava.lang.I llegalMonitorStateExceptionを放出する可能性があります.
まずjava.lang.I llegalMonitorStateExceptionの説明を見てみましょう.
それから2段のコードを貼って、まずこの異常を投げ出すコードです.
このコードのスレッドはwaitメソッドとnotifyallメソッドを呼び出すとlockの同期ロックが得られず、モニタが指定されていないことに等しい.
例外を投げ出さないコードをもう1つください.
このコードはwaitメソッドを実行する前にlockの同期が得られるため、上記の異常は発生しません.
waitメソッドの実行時にロックが解放されるので、同期ブロックで実行しないと異常が発生する可能性があります.
waitに似たsleepメソッドは実行時にロックを解放しません.これはブロック防止に注意する必要があります.
まずjava.lang.I llegalMonitorStateExceptionの説明を見てみましょう.
public class IllegalMonitorStateExceptionextends RuntimeException
, 。
:
JDK1.0
それから2段のコードを貼って、まずこの異常を投げ出すコードです.
package com.wikimore.threadtest;
/**
* Hello world!
*
*/
public class App {
private static Object lock = new Object();
public static void main(String[] args) {
Runnable r1 = new Runnable() {
public void run() {
System.out.println("t1 running");
try {
System.out.println("t1 waiting");
lock.wait();
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t1 running again");
lock.notifyAll();
}
};
Thread t1 = new Thread(r1, "thread-1");
Runnable r2 = new Runnable() {
public void run() {
System.out.println("t2 running");
try {
System.out.println("t2 waiting");
lock.wait();
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t2 running again");
lock.notifyAll();
}
};
Thread t2 = new Thread(r2, "thread-2");
Runnable r3 = new Runnable() {
public void run() {
System.out.println("t3 running");
try {
System.out.println("t3 waiting");
lock.wait(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t3 running again");
lock.notifyAll();
}
};
Thread t3 = new Thread(r3, "thread-3");
t1.start();
t2.start();
t3.start();
}
}
このコードのスレッドはwaitメソッドとnotifyallメソッドを呼び出すとlockの同期ロックが得られず、モニタが指定されていないことに等しい.
例外を投げ出さないコードをもう1つください.
package com.wikimore.threadtest;
/**
* Hello world!
*
*/
public class App {
private static Object lock = new Object();
public static void main(String[] args) {
Runnable r1 = new Runnable() {
public void run() {
System.out.println("t1 running");
synchronized (lock) {
try {
System.out.println("t1 waiting");
lock.wait();
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t1 running again");
lock.notifyAll();
}
}
};
Thread t1 = new Thread(r1, "thread-1");
Runnable r2 = new Runnable() {
public void run() {
System.out.println("t2 running");
synchronized (lock) {
try {
System.out.println("t2 waiting");
lock.wait();
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t2 running again");
lock.notifyAll();
}
}
};
Thread t2 = new Thread(r2, "thread-2");
Runnable r3 = new Runnable() {
public void run() {
System.out.println("t3 running");
synchronized (lock) {
try {
System.out.println("t3 waiting");
lock.wait(10000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t3 running again");
lock.notifyAll();
}
}
};
Thread t3 = new Thread(r3, "thread-3");
t1.start();
t2.start();
t3.start();
}
}
このコードはwaitメソッドを実行する前にlockの同期が得られるため、上記の異常は発生しません.
waitメソッドの実行時にロックが解放されるので、同期ブロックで実行しないと異常が発生する可能性があります.
waitに似たsleepメソッドは実行時にロックを解放しません.これはブロック防止に注意する必要があります.