了解Java Wait和Notify方法

时间:2010-04-12 18:45:44

标签: java multithreading wait

我有以下计划:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class SimpleWaitNotify implements Runnable {

final static Object obj = new Object();
static boolean value = true;

public synchronized void flag()  {
    System.out.println("Before Wait");
    try {
        obj.wait();
    } catch (InterruptedException e) {
        System.out.println("Thread interrupted");
    }
    System.out.println("After Being Notified");
}

public synchronized void unflag() {
    System.out.println("Before Notify All");
    obj.notifyAll();
    System.out.println("After Notify All Method Call");
}

public void run() {
    if (value) {
        flag();
    } else {
        unflag();
    }
}

public static void main(String[] args) throws InterruptedException {
    ExecutorService pool = Executors.newFixedThreadPool(4);
    SimpleWaitNotify sWait = new SimpleWaitNotify();
    pool.execute(sWait);
    SimpleWaitNotify.value = false;
    SimpleWaitNotify sNotify = new SimpleWaitNotify();
    pool.execute(sNotify);
    pool.shutdown();

}

}

当我等待obj时,我会为两个线程中的每一个获得以下异常Exception in thread "pool-1-thread-1" java.lang.IllegalMonitorStateException: current thread not owner

但是如果我使用SimpleWaitNotify的监视器,那么程序执行将被暂停。换句话说,我认为它暂停当前的执行线程,反过来执行器。任何有助于理解正在发生的事情的帮助都将得到适当的赞赏。

这是一个理论和javadoc看起来很简单的区域1,并且因为没有很多例子,所以在概念上给我留下了很大的空白。

3 个答案:

答案 0 :(得分:12)

您在wait上正在呼叫notifyAllobj,但您正在this进行同步(因为您已获得同步方法)。

为了等待或通知,您需要先“拥有”监视器。取消同步方法,并在obj上同步:

public void flag()  {
    System.out.println("Before Wait");
    synchronized (obj) {
        try {
            obj.wait();
        } catch (InterruptedException e) {
            System.out.println("Thread interrupted");
        }
    }
    System.out.println("After Being Notified");
}

public void unflag() {
    System.out.println("Before Notify All");
    synchronized (obj) {
        obj.notifyAll();
    }
    System.out.println("After Notify All Method Call");
}

答案 1 :(得分:3)

synchronize上的obj,或wait上的notifythis。调用线程必须保存调用这些方法的相同对象的监视器。

例如,

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();
  }

}

答案 2 :(得分:1)

而是直接声明pool.shutdown(),请尝试如下。

while (!service.isTerminated())
{
    service.shutdown();
}

因此它将等待所有线程执行完成。