我做了以下代码示例,它测试同一个锁定对象的wait()
和notifyAll()
。 Receiver线程正在等待锁定的对象,而Sender线程激活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.");
}
}
}
}
}
输出结果为:
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
我的问题是 - 为什么接收方没有到达“中断的”消息?
第二个问题: 如果我将Receiver线程的等待时间更改为100ms,则输出为:
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
查看时间戳,您会看到接收器花了3秒时间到达“超时”消息,而不是100毫秒。 3秒是发送方在使用notifyAll()之前处于活动状态的时间。 你能解释为什么3秒而不是100毫秒?
答案 0 :(得分:1)
当通知锁时,方法wait
只返回,不会抛出异常。使用InterruptException
中断线程时抛出Thread.interrupt()
,而不是在通知锁定时抛出。{/ p>
答案 1 :(得分:0)
说到第二个问题 - 发件人睡3秒钟,保持锁定。如果您希望线程停止执行并释放锁定,请使用wait(3000)而不是sleep(3000)。