I am trying to make a wait in java using Thread, but i get the error:
Exception in thread "main" java.lang.IllegalMonitorStateException: current thread is not owner
I have tried
Thread t = new Thread();
try {
t.wait(2000);
} catch (InterruptedException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
but It didn't work, I've searched StackOverFlow for answers but I couldn't find anything useful
wait
is a low-level construct designed to wait until something happens, and that something is not primarily 'x amount of time has passed'. It's for some other thread to signal: This is the moment.. wake up!
If you just want the thread to wait for a provided amount of time, the call you are looking for is not t.wait
, but is Thread.sleep(1000)
- that sleeps for 1 second (1000 milliseconds).
wait
goes together with notify
/notifyAll
(those 2 methods do almost the same thing). One thread waits, another thread calls notify which causes the first thread to wake up. Yes, there is an overloaded variant of wait
that takes an amount of milliseconds; that variant will wait until EITHER the stated amount of time has passed OR notify is called; whichever one occurs earlier.
To use wait/notify you need an object (and all objects can do this; in retrospect that wasn't a great way to design this part of the java language but it is what it is; changing it now would be quite backwards incompatible) - you need an object because different parts of your code can choose to do this wait/notify thing at the same time and it wouldn't do if they are all confused about who is signalling whom.
In addition, this notion of 'I wait until you tell me to resume' tends to run into some pretty severe threading errors very quickly, so in practice and because such a signal needs some sort of CPU gating anyway, java requires that you own the monitor on that object before you wait OR notify on it. Combining it all, this is what that looks like:
public class TrainStationPlatform {
private final Object lock = new Object();
private Train atPlatform = null;
public void enterStation(Train train) {
synchronized (lock) {
while (atPlatform != null) {
// Oh no! There's a train already at the platform!
lock.wait(); // let's wait for it to leave.
}
// The platform is clear, we can enter!
atPlatform = train;
}
}
public void leave() {
synchronized (lock) {
if (atPlatform == null) throw new IllegalStateException("No train");
atPlatform = null;
lock.notifyAll();
}
}
}
This shows how you can use this:
enter(this)
and leave()
on its own. Any train trying to enter when there's a different train already at the platform will 'freeze' (its enter
call will pause until the already-there train takes off, and then it will enter the platform, and the enter
method returns).x.notify
or x.wait
unless you are inside a synchronized (x)
block, where all x
-es are referring to the same object.t.wait()
where t
is a thread is never a correct action. Do not do this.synchronized
) is needed. Imagine the synchronized stuff wasn't there - you would draw the conclusion there is a train and in between drawing that conclusion and calling wait(), let's say the other thread makes the train that is there go away. You're still calling wait, waiting for an event that will never happen (because the train already left). This is the kind of crazy trickery that this construction avoids entirely by requiring that you lock on the think you want to call wait on first. The above code can never run into that problem.x.wait()
, your lock on x
(the synchronized
block, freezing all other threads that want to enter such a synchronized construct) is relinquished - other threads can now enter.wait
call returns (whether by timeout if you use that, or because someone called notify), your thread does not immediately continue. After all, calling notify requires having the lock, and wait() won't continue until it has re-acquired it, which means it has to wait for whatever called notify to get to the end of its synchronized block first.notify()
wakes up a random wait()
ing thread, notifyAll()
wakes them all up. It tends to be more sensible to perform the check to confirm whatever you need is there (or not there and requires wait()
ing for) in a loop, and use notifyAll()
. Easier to reason about, and there is no meaningful performance difference.java.util.concurrent
package that is easier to use and makes more sense for whatever inter-thread signalling needs you have.Thread.sleep
instead.private
- you want to keep very careful track of who uses it as a lock, which you can't do if code outside of your direct control can see that object. If you make it public, you either add extensive documentation explaining precisely what any code that acquires this object can and cannot do and how it is supposed to use it, or your code is a buggy mess that is going to result, sooner rather than later, in very nasty intermittent heisenbugs that take months to fix or end up being unfixable. So, don't.java.lang.IllegalMonitorStateException: current thread is not owner
occurs when you invoke x.wait
or x.notify/notifyAll
when you are not in a synchronized (x)
block.private Object lock = new Object[0]
. arrays are serializable; new Object()
is not, and new Object[0]
is as light weight as they come.