wait()不会被notifyAll()中断

时间:2015-04-13 13:38:44

标签: java

我做了以下代码示例,它测试同一个锁定对象的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毫秒?

2 个答案:

答案 0 :(得分:1)

当通知锁时,方法wait只返回,不会抛出异常。使用InterruptException中断线程时抛出Thread.interrupt(),而不是在通知锁定时抛出。{/ p>

答案 1 :(得分:0)

说到第二个问题 - 发件人睡3秒钟,保持锁定。如果您希望线程停止执行并释放锁定,请使用wait(3000)而不是sleep(3000)。