To illustrate my problem, and as we are in easter eggs period, here is the storyboard : The first character is a clock is giving periodically the time. But this clock is very moody : it doesn't answer to a user who ask time but inform all his observers periodically and this period is randomly defined. My second character is a very stressed rabbit. This rabbit can't do anything unless he knows the time. And when he finished his action, he asks again the time and waits to get it before doing something else. I could add other characters (a cat, a mad hat-maker...) but for this example, it's not necessary.
So, in Java, I'll have a clock which is observable by observers, whatever the type of observers ; and a rabbit which is a type of observer. I want to keep the pattern «observable / observer» as the clock don't know and don't care who are the observers.
Here are the class I'm using :
Clock
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);
}
Rabbit
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»
}
}
Main
public class Main {
public static void main(String[] args) {
Clock clock = new Clock();
Thread thread = new Thread (clock);
thread.start();
new Rabbit(clock);
}
}
The problem is the following instruction in the Rabbit class, in the overrided update method, which generates a «java.lang.IllegalMonitorStateException».
Rabbit.this.notifyAll();
And, indeed, the Rabbit is on the Main thread and the notify is on the thread-0.
But, what can I do ? How to solve my problem ?
Thank you for all your answers.
Dr_Click