Либо synchronize
на obj
, либо звоните wait
и notify
на this
. Вызывающий поток должен содержать монитор того же объекта , для которого вызываются эти методы.
Например,
synchronized void flag() {
System.out.println("Before Wait");
try {
wait();
} catch (InterruptedException e) {
System.out.println("Thread interrupted");
}
System.out.println("After Being Notified");
}
В этом примере блокировка удерживается на this
(когда модификатор synchronized
используется в методе экземпляра, монитор экземпляра получается). Таким образом, метод wait()
может быть вызван на подразумеваемом экземпляре this
.
Чтобы согласовать два потока, им необходимо использовать один и тот же замок . Первоначальная версия имела статический obj
, который можно было использовать в качестве блокировки, но он не использовался в блоках synchronized
. Вот лучший пример:
class SimpleWaitNotify implements Runnable {
private final Object lock;
private final boolean wait;
SimpleWaitNotify(Object lock, boolean wait) {
this.lock = lock;
this.wait = wait;
}
public void flag() {
synchronized (lock) {
System.out.println("Before Wait");
try {
lock.wait();
System.out.println("After Being Notified");
} catch (InterruptedException ex) {
System.out.println("Thread interrupted");
}
}
}
public void unflag() {
synchronized(lock) {
System.out.println("Before Notify All");
lock.notifyAll();
System.out.println("After Notify All Method Call");
}
}
public void run() {
if (wait) {
flag();
} else {
unflag();
}
}
public static void main(String[] argv) throws Exception {
ExecutorService pool = Executors.newFixedThreadPool(4);
Object shared = new Object();
SimpleWaitNotify sWait = new SimpleWaitNotify(shared, true);
pool.execute(sWait);
SimpleWaitNotify sNotify = new SimpleWaitNotify(shared, false);
pool.execute(sNotify);
pool.shutdown();
}
}