代码:
public class NotifyAndWaitTest2 implements Runnable {
public int i = 0;
public Object lock;
public SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
public NotifyAndWaitTest2(Object o) {
this.lock = o;
}
@Override
public void run() {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + " enter the SYNCHRONIZED block --- "+ sdf.format(new Date()));
try {
while (i < 9) {
Thread.sleep(500);
lock.notify();
lock.wait();
System.out.println(Thread.currentThread().getName() + " say:" + i++ + " --- " + sdf.format(new Date()));
}
lock.notify();
return;
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Object lock = new Object();
NotifyAndWaitTest2 test = new NotifyAndWaitTest2(lock);
Thread t1 = new Thread(test,"Thread A");
Thread t2 = new Thread(test,"Thread B");
Thread t3 = new Thread(test,"Thread C");
Thread t4 = new Thread(test,"Thread D");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
结果:
Thread A enter the SYNCHRONIZED block --- 10:47:07.242
Thread B enter the SYNCHRONIZED block --- 10:47:07.743
Thread C enter the SYNCHRONIZED block --- 10:47:08.243
Thread D enter the SYNCHRONIZED block --- 10:47:08.743
Thread C say:0 --- 10:47:09.243
Thread D say:1 --- 10:47:09.744
Thread C say:2 --- 10:47:10.244
Thread D say:3 --- 10:47:10.744
Thread C say:4 --- 10:47:11.245
Thread D say:5 --- 10:47:11.745
Thread C say:6 --- 10:47:12.246
Thread D say:7 --- 10:47:12.746
Thread C say:8 --- 10:47:13.247
Thread D say:9 --- 10:47:13.247
Thread B say:10 --- 10:47:13.247
Thread A say:11 --- 10:47:13.247
代码在jdk1.7和jdk1.8中执行相同的结果。
我的问题:
在线程A和线程B进入SYNCHRONIZED块并调用wait()方法之后,为什么线程C和线程D进入而不是线程A说i然后线程B说i?进入同步块的优先级是否高于刚调用wait()方法的线程?
为什么调用notify()方法只是唤醒那个调用wait()方法的最新线程?就像线程C和线程D一样,互相通知并等待对方,为什么不等待任何其他线程呢?像线程A和线程B。
我认为它应该是随机的,比如
Thread A enter the SYNCHRONIZED block
Thread B enter the SYNCHRONIZED block
Thread A say:0
Thread C enter the SYNCHRONIZED block
Thread B say:1
Thread A say:2
Thread D enter the SYNCHRONIZED block
Thread B say:3
Thread C say:4
答案 0 :(得分:1)
问题1:
在线程A和线程B之后进入SYNCHRONIZED块并调用 wait()方法,为什么线程C和线程D进入而不是线程 说我然后线程B说我?是进入同步的优先级 阻止高于刚调用wait()方法的线程?
以下是Javadoc关于等待/通知的内容:
唤醒的线程将无法继续直到当前 线程放弃对此对象的锁定。 被唤醒的线程会 以通常的方式与任何其他可能的线程竞争 积极竞争同步这个对象;例如, 被唤醒的线程没有可靠的特权或劣势 下一个锁定此对象的线程。
这意味着当线程B调用notify
并且线程A需要与在同步块开始时等待的线程C和D竞争时,线程A将不能保证继续。在您的情况下,实现只优先考虑线程C和D.这就是你看到这个输出的原因:
Thread A enter the SYNCHRONIZED block --- 10:47:07.242
Thread B enter the SYNCHRONIZED block --- 10:47:07.743
Thread C enter the SYNCHRONIZED block --- 10:47:08.243
Thread D enter the SYNCHRONIZED block --- 10:47:08.743
问题2:
为什么调用notify()方法只是唤醒调用的最新线程 wait()方法?就像线程C和线程D一样,互相通知 并等待对方,为什么不等任何其他等待线程?喜欢线程 A和线程B。
Java规范再次不保证优先级。只是从线程D调用notify
唤醒线程C(等待锁定,连同线程A和B)并在打印出“说”语句后从线程C调用并休眠500ms唤醒线程D(它再次等待锁定,连同线程A和B),直到它们在循环和同步块退出时,从而首先将锁定释放到线程B,然后释放到线程A。
我跑步的示例输出:
Thread A enter the SYNCHRONIZED block --- 09:35:59.836
Thread D enter the SYNCHRONIZED block --- 09:36:00.336
Thread C enter the SYNCHRONIZED block --- 09:36:00.836
Thread B enter the SYNCHRONIZED block --- 09:36:01.336
Thread C say:0 --- 09:36:01.836
Thread B say:1 --- 09:36:02.337
Thread C say:2 --- 09:36:02.837
Thread B say:3 --- 09:36:03.337
Thread C say:4 --- 09:36:03.837
Thread B say:5 --- 09:36:04.337
Thread C say:6 --- 09:36:04.837
Thread B say:7 --- 09:36:05.337
Thread C say:8 --- 09:36:05.837
Thread B say:9 --- 09:36:05.837
Thread D say:10 --- 09:36:05.837
Thread A say:11 --- 09:36:05.838