I have a ThreadManager with two Threads. One for gui-relevant requests and one for measurement-relevant requests. The are both running and checking their queue of requests, if there is any, they are processing the request. One can add requests at any time, using the static ThreadManager.addGuiRequest(eGuiRequest)
and ThreadManager.addMeasRequest(eMeasRequest)
methods. Now both of those need to be initialized which is done by adding a INIT
request to the corresponding queue. But the initialization of the measurement is depending on the fact that the gui is already initialized. I tried to solve this using wait()/notify()
, but I can not get it working.
Here is a SSCCE. At startup, both queues have a INIT request added and are then started. The measurement initialization detects that the gui is not yet initialized and perfomrs a wait()
. The gui initializes (simulated by sleeping for 5s). This all works fine.
After the gui initialized, it tries to wake up the measurement thread, but the measurement thread does not wake up... I based my wait()/notify()
code on this article. What is going wrong here?
import java.util.LinkedList;
import java.util.NoSuchElementException;
public class ThreadManager {
public static void main(String[] args) {
new ThreadManager();
ThreadManager.addMeasRequest(eMeasRequest.OTHER_STUFF);
}
public enum eGuiRequest { INIT, OTHER_STUFF; }
public enum eMeasRequest { INIT, OTHER_STUFF; }
private static LinkedList<eGuiRequest> guiQueue = new LinkedList<eGuiRequest>();
private static LinkedList<eMeasRequest> measQueue = new LinkedList<eMeasRequest>();
private static Thread guiThread, measThread;
protected boolean initialized = false;
public ThreadManager() {
final int waitMs = 200;
guiThread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
if (guiQueue.isEmpty()) sleepMs(waitMs);
else {
eGuiRequest req = guiQueue.getFirst();
processGuiRequest(req);
guiQueue.removeFirst();
}
} catch (NoSuchElementException e) {}
}
}
private void processGuiRequest(eGuiRequest req) {
System.out.println("T: " + "Processing Gui request: " + req);
switch (req) {
case INIT:
// do some initializiation here - replaced by a wait:
sleepMs(5000);
System.out.println("I: " + "guiThread finished, waking up measThread");
synchronized (measThread) {
initialized = true;
measThread.notify();
}
break;
case OTHER_STUFF:
// do other stuff
break;
}
}
});
measThread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
if (measQueue.isEmpty()) sleepMs(waitMs);
else {
eMeasRequest req = measQueue.getFirst();
processMeasurementRequest(req);
measQueue.removeFirst();
}
} catch (NoSuchElementException e) {}
}
}
private void processMeasurementRequest(eMeasRequest req) {
if (req == eMeasRequest.INIT) { // if init, wait until GUI is initialized
synchronized (this) {
while (!initialized) {
System.out.println("I: " + "measThread waits for guiThread to finish initializiation");
try {
wait();
} catch (Exception e) {}
System.out.println("I: " + "measThread awakes");
}
}
}
System.out.println("T: " + "Processing Measurement request: " + req);
// process request here:
sleepMs(5000);
}
});
addGuiRequest(eGuiRequest.INIT);
addMeasRequest(eMeasRequest.INIT);
guiThread.start();
measThread.start();
}
public static void sleepMs(int ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException ee) {}
}
public static void addGuiRequest(eGuiRequest req) {
guiQueue.add(req);
}
public static void addMeasRequest(eMeasRequest req) {
measQueue.add(req);
}
}