7

我有以下程序:

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,由于没有太多示例,因此在概念上给我留下了很大的空白。

4

3 回答 3

12

你正在调用waitand 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");
}
于 2010-04-12T18:48:27.250 回答
3

要么synchronizeon obj,要么调用waitand notifyon 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();
  }

}
于 2010-04-12T18:57:51.770 回答
1

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

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

所以它会一直等到所有线程执行完成。

于 2013-03-04T06:17:50.823 回答