我有以下计划:
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,并且因为没有很多例子,所以在概念上给我留下了很大的空白。
答案 0 :(得分:12)
您在wait
上正在呼叫notifyAll
和obj
,但您正在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
上的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();
}
}
答案 2 :(得分:1)
而是直接声明pool.shutdown()
,请尝试如下。
while (!service.isTerminated())
{
service.shutdown();
}
因此它将等待所有线程执行完成。