notifyAll() 不起作用
notifyAll() does not work
在下面的代码中调用了 notifyAll() 但没有重新激活其他线程。我得到的输出是
beta等待通知时间:1441870698303,activeWriters:1
alpha 等待通知时间:1441870698303,activeWriters:1
增量通知时间:1441870698403,activeWriters:0
public class Waiter 实现 Runnable{
private static int activeWriters;
public Waiter(Message msg){
}
@Override
public void run() {
beforeWrite();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
afterWrite();
}
protected synchronized void beforeWrite(){
while (activeWriters > 0 ) {
try {
System.out.println(Thread.currentThread().getName() +" waiting to get notified at time: "+System.currentTimeMillis()+ ", activeWriters: " + activeWriters);
wait();
System.out.println(Thread.currentThread().getName() +" waiting got notified at time: "+System.currentTimeMillis()+ ", activeWriters: " + activeWriters);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
++activeWriters;
}
protected synchronized void afterWrite(){
--activeWriters;
System.out.println(Thread.currentThread().getName() +" notify all at time: "+System.currentTimeMillis() + ", activeWriters: " + activeWriters);
notifyAll();
}
}
public class WaitNotifyTest {
public static void main(String[] args) {
Message msg = new Message("process it");
Waiter waiter1 = new Waiter(msg);
Waiter waiter2 = new Waiter(msg);
Waiter waiter3 = new Waiter(msg);
new Thread(waiter1,"alpha").start();
new Thread(waiter2, "beta").start();
new Thread(waiter3, "delta").start();
}
}
调用wait()
和notify*()
作用于指定的对象,这意味着notify*()
唤醒在同一个对象上调用wait()
的线程。
在您的情况下,您在 3 个未连接的不同对象上调用了 wait()
和 notifyAll()
,因此这行不通。
您可以添加静态互斥体:
private static final Object mutex = new Object();
然后对该对象调用 wait()
和 notify*()
。记得先在互斥锁上同步:
synchronized (mutex) {
...
mutex.wait();
...
}
和:
synchronized (mutex) {
...
mutex.notifyAll();
...
}
所有对 activeWriters
的访问都必须在这些 synchronized
块中,原因有两个。目前对它的访问实际上是不同步的,因为您在 3 个不同的对象上同步。除此之外 activeWriters
是你的条件变量,你想要 notify*()
它改变的其他线程。为此,变量的更改和 notify*()
调用必须在同一个 synchronized
块中。
您的程序存在重大设计缺陷。
您正在创建 3 个独立的 Waiter class 实例,并期望它们都以同步方式访问 activeWriters
。这是不可能的,因为实例方法将获取不同的锁但修改相同的静态变量 activeWriters
.
要提供静态变量并发访问,你应该通过访问它们。同步静态方法。
一种方法是制作 beforeWrite()
和 afterWrite()
方法 static
.
在下面的代码中调用了 notifyAll() 但没有重新激活其他线程。我得到的输出是
beta等待通知时间:1441870698303,activeWriters:1
alpha 等待通知时间:1441870698303,activeWriters:1
增量通知时间:1441870698403,activeWriters:0
public class Waiter 实现 Runnable{
private static int activeWriters; public Waiter(Message msg){ } @Override public void run() { beforeWrite(); try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } afterWrite(); } protected synchronized void beforeWrite(){ while (activeWriters > 0 ) { try { System.out.println(Thread.currentThread().getName() +" waiting to get notified at time: "+System.currentTimeMillis()+ ", activeWriters: " + activeWriters); wait(); System.out.println(Thread.currentThread().getName() +" waiting got notified at time: "+System.currentTimeMillis()+ ", activeWriters: " + activeWriters); } catch (InterruptedException e) { e.printStackTrace(); } } ++activeWriters; } protected synchronized void afterWrite(){ --activeWriters; System.out.println(Thread.currentThread().getName() +" notify all at time: "+System.currentTimeMillis() + ", activeWriters: " + activeWriters); notifyAll(); } } public class WaitNotifyTest { public static void main(String[] args) { Message msg = new Message("process it"); Waiter waiter1 = new Waiter(msg); Waiter waiter2 = new Waiter(msg); Waiter waiter3 = new Waiter(msg); new Thread(waiter1,"alpha").start(); new Thread(waiter2, "beta").start(); new Thread(waiter3, "delta").start(); } }
调用wait()
和notify*()
作用于指定的对象,这意味着notify*()
唤醒在同一个对象上调用wait()
的线程。
在您的情况下,您在 3 个未连接的不同对象上调用了 wait()
和 notifyAll()
,因此这行不通。
您可以添加静态互斥体:
private static final Object mutex = new Object();
然后对该对象调用 wait()
和 notify*()
。记得先在互斥锁上同步:
synchronized (mutex) {
...
mutex.wait();
...
}
和:
synchronized (mutex) {
...
mutex.notifyAll();
...
}
所有对 activeWriters
的访问都必须在这些 synchronized
块中,原因有两个。目前对它的访问实际上是不同步的,因为您在 3 个不同的对象上同步。除此之外 activeWriters
是你的条件变量,你想要 notify*()
它改变的其他线程。为此,变量的更改和 notify*()
调用必须在同一个 synchronized
块中。
您的程序存在重大设计缺陷。
您正在创建 3 个独立的 Waiter class 实例,并期望它们都以同步方式访问 activeWriters
。这是不可能的,因为实例方法将获取不同的锁但修改相同的静态变量 activeWriters
.
要提供静态变量并发访问,你应该通过访问它们。同步静态方法。
一种方法是制作 beforeWrite()
和 afterWrite()
方法 static
.