Reputation: 49
I've made the following code sample, which tests wait()
and notifyAll()
of the same locked object. Receiver thread is waiting on the locked object, while Sender thread activates the notifyAll()
.
public class MonitorState {
private static complexObj lock = new complexObj();
public static void main(String[] args) {
writeLog("Main - \tLocker name = " + lock.getName());
writeLog("Main - \tLocker code = " + lock.getCode());
try {
Thread receiver = new Receiver();
Thread sender = new Sender();
receiver.start();
sender.start();
Thread.sleep(5000);
writeLog("Main - \tLocker name = " + lock.getName());
writeLog("Main - \tLocker code = " + lock.getCode());
}
catch (Exception e) {
writeLog(e.getMessage());
e.printStackTrace();
}
}
private static void writeLog(String msg) {
Date time = new Date(System.currentTimeMillis());
SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss.S");
System.out.println(df.format(time) + " " + msg);
}
// locking object
private static class complexObj {
private String name = "complexObj";
private Integer code = 0;
public complexObj() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
}
private static class Receiver extends Thread {
public Receiver() {
}
@Override
public void run() {
int timeout = 100;
try{
synchronized (lock) {
writeLog("Receiver - Waiting for " + timeout + " ms.");
lock.wait(timeout);
}
}
catch (InterruptedException e) {
writeLog("Receiver - Interrupted.");
}
writeLog("Receiver - Timed out.");
writeLog("Receiver - Locker code = " + lock.getCode());
if (lock.getCode() == 0) {
writeLog("Receiver - Setting values into the locker.");
lock.setName("Receiver");
lock.setCode(2);
}
}
}
private static class Sender extends Thread {
public Sender() {
}
@Override
public void run() {
synchronized (lock) {
try {
int sleepTime = 3000;
writeLog("Sender - \tSleeping for " + sleepTime + " ms.");
sleep(sleepTime);
writeLog("Sender - \tSetting values into the locker.");
lock.setName("Sender");
lock.setCode(1);
lock.notifyAll();
}
catch (InterruptedException e) {
writeLog("Sender - \tInterrupted.");
}
}
}
}
}
The output is:
16:17:52.191 Main - Locker name = complexObj
16:17:52.237 Main - Locker code = 0
16:17:52.237 Receiver - Waiting for 4000 ms.
16:17:52.238 Sender - Sleeping for 3000 ms.
16:17:55.238 Sender - Setting values into the locker.
16:17:55.238 Receiver - Timed out.
16:17:55.238 Receiver - Locker code = 1
16:17:57.237 Main - Locker name = Sender
16:17:57.237 Main - Locker code = 1
My question is - why isn't the Receiver reaches to the "Interrupted" message?
Second question: If I change the wait time for the Receiver thread to 100ms, the output is:
16:31:21.522 Main - Locker name = complexObj
16:31:21.571 Main - Locker code = 0
16:31:21.571 Receiver - Waiting for 100 ms.
16:31:21.571 Sender - Sleeping for 3000 ms.
16:31:24.572 Sender - Setting values into the locker.
16:31:24.572 Receiver - Timed out.
16:31:24.572 Receiver - Locker code = 1
16:31:26.571 Main - Locker name = Sender
16:31:26.571 Main - Locker code = 1
Looking at the timestamp, you see that it took 3 seconds for the Receiver to get to the "Timed out" message, and not 100ms as it should have. 3 seconds is the time the sender is active before using the notifyAll(). Can you please explain why 3 seconds and not 100ms?
Upvotes: 0
Views: 159
Reputation: 328
When it comes to the second question - the Sender sleeps for 3 seconds, keeping the lock. If you want a thread to cease execution and release the lock, use wait(3000) instead of sleep(3000).
Upvotes: 0
Reputation: 9619
When the lock is notified, the method wait
just returns, no exception is thrown. InterruptException
is thrown when the thread is interrupted using Thread.interrupt()
, not when the lock is notified.
Upvotes: 1