为了说明我的问题,在复活节彩蛋时代,这是分镜脚本:第一个字符是时钟,它会定期提供时间。但是此时钟非常令人讨厌:它不会回答询问时间但会定期通知所有观察者的用户,并且此时间段是随机定义的。我的第二个角色是一只压力很大的兔子。除非他知道时间,否则这只兔子什么也做不了。当他完成动作时,他会再次询问时间并等待获取时间,然后再执行其他操作。我可以添加其他字符(一只猫,一个疯狂的帽子制造商...),但是对于此示例,则没有必要。
因此,在Java中,无论观察者的类型如何,我都会有一个观察者可以观察到的时钟;还有一只是观察者的兔子我想保持模式“可观察/观察者”,因为时钟不知道,也不在乎谁是观察者。
这是我正在使用的班级:
时钟
public class Clock implements Runnable, ClockObservable {
private Long time;
public Clock () {
}
@Override
public void run() {
while (true) {
time=System.currentTimeMillis();
update();
try {
int randomTimeUpdate=(int)( (Math.random() + 1) *500); //This clock will update randomly
Thread.sleep(randomTimeUpdate);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void update() {
for (ClockObserver observer : observers) {
observer.update(time);
}
}
}
ClockObservable
import java.util.ArrayList;
public interface ClockObservable {
public static ArrayList<ClockObserver> observers = new ArrayList<ClockObserver>();
public default void addObserver (ClockObserver observer) {
observers.add(observer);
}
public default void resetObservers () {
observers.clear();
}
public void update ();
}
ClockObserver
public interface ClockObserver {
public void update(Long time);
}
兔子
public class Rabbit implements ClockObserver {
Long time;
public Rabbit (Clock clock) {
clock.addObserver(this);
whatTimeIsIt();
}
public synchronized void whatTimeIsIt () {
while (true) {
System.out.println("What time is it ?");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("It's "+time+" -> Yepeeeee !!!! I can do something before asking the time again...");
System.out.println("-----------------------------------");
}
}
@Override
public void update(Long time) {
this.time=time;
System.out.println("Time = "+time);
//How can I notify the rabbit ?
Rabbit.this.notifyAll(); //This cause a «java.lang.IllegalMonitorStateException»
}
}
主要
public class Main {
public static void main(String[] args) {
Clock clock = new Clock();
Thread thread = new Thread (clock);
thread.start();
new Rabbit(clock);
}
}
问题是Rabbit类中重写的update方法中的以下指令,该指令生成«java.lang.IllegalMonitorStateException»。
Rabbit.this.notifyAll();
并且,实际上,Rabbit在主线程上,通知在线程0上。
但是,我该怎么办?如何解决我的问题?
谢谢您的所有回答。
Dr_Click
public void update(Long time) {
this.time=time;
System.out.println("Time = "+time);
//How can I notify the rabbit ?
Rabbit.this.notifyAll(); //This cause a «java.lang.IllegalMonitorStateException»
}
notifyAll
函数用于通知其他线程某些共享状态已更改。此处共享状态没有更改,因此没有任何通知其他线程的信息。如果您认为this.time
是共享状态,请解释为什么不同步的方法修改它而不持有任何锁。您无法使用共享状态来做到这一点。
public synchronized void whatTimeIsIt () {
while (true) {
System.out.println("What time is it ?");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
这里有同样的问题。您在呼叫wait
时没有检查您正在等待的事情还没有发生。你在等什么?什么是共享状态,而不是您需要处于的状态?
您不能使用wait
,除非等待某些共享状态具有一定的价值。您不能使用notify
来通知另一个线程共享状态已更改。
您当前的代码没有任何意义,因为它不等待任何东西,也不通知任何东西。notify
/ wait
函数不具有Sempahores的语义。他们没有自己的共享状态。您必须实现共享状态。