Either synchronize on obj , or call wait and notify on this . The calling thread must contain a monitor of the same object on which these methods are called.
For example,
synchronized void flag() { System.out.println("Before Wait"); try { wait(); } catch (InterruptedException e) { System.out.println("Thread interrupted"); } System.out.println("After Being Notified"); }
In this example, the lock is held on this (when the synchronized modifier is used in the instance method, the instance monitor will be retrieved). Thus, the wait() method can be called on an alleged instance of this .
In order to coordinate the two threads, they need to share the same lock. The original version had a static obj that could be used as a lock, but was not used in synchronized blocks. Here is a better example:
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(); } }
erickson
source share