在以下代码中,调用notifyAll()但不重新激活其他线程。我得到的输出是
测试版等待及时通知:1441870698303,activeWriters:1
alpha等待及时收到通知:1441870698303,activeWriters:1
delta通知所有时间: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();
}
}
答案 0 :(得分:4)
调用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
块中。
答案 1 :(得分:0)
您的计划存在重大设计缺陷。
您正在创建3个单独的Waiter类实例,并期望它们以同步方式访问activeWriters
。这是不可能的,因为实例方法将获取不同的锁,但修改相同的静态变量activeWriters
。
要提供静态变量并发访问,您应该通过它来访问它们。同步静态方法。
一种方法是制作beforeWrite()
和afterWrite()
方法static
。