class Useless {
public static boolean b = true;
public synchronized void u1() {
try {
while (b == true)
wait();
} catch (InterruptedException i) {
}
}
public synchronized void u2() {
if (b == true) {
b = false;
}
notify();
}
}
public class SleepMessages extends Thread {
private Useless u;
public SleepMessages(Useless u) {
this.u = u;
}
public void run() {
String importantInfo[] = { "Mares eat oats", "Does eat oats" };
for (int i = 0; i < importantInfo.length; i++) {
u.u1();
System.out.println(importantInfo[i] + " - " + getName());
try {
sleep(2000);
} catch (InterruptedException e) {
}
}
}
public static void main(String args[]) throws InterruptedException {
Useless u = new Useless();
Thread t1 = new SleepMessages(u);
t1.setName("t1");
Thread t2 = new SleepMessages(u);
t2.setName("t2");
t1.start();
t2.start();
sleep(2000);
System.out.println("Here they go!...");
t1.interrupt();
sleep(1000);
t2.interrupt();
u.u2();
sleep(1000);
u.u2();
}
}
这个小程序的输出给出: 他们走了!... Mares吃燕麦 - t1 Mares吃燕麦 - t2 吃燕麦 - t2 吃燕麦 - t1
我的问题是为什么线程t2是进入catch的唯一一个(InterruptedException e),为什么结果不是这样的:
他们走了!... Mares吃燕麦 - t1 Mares吃燕麦 - t2 吃燕麦 - t1 吃燕麦 - t2
答案 0 :(得分:1)
我的问题是为什么线程t2是进入catch的唯一一个(InterruptedException e),
我认为t1.interrupt()
正在中断run()方法中的睡眠。一旦丢弃了InterruptedException,就无法知道线程在之前被中断了。
为什么结果不是这样的: 他们去了!......妈妈吃燕麦 - t1妈妈吃燕麦 - t2吃燕麦 - t1吃燕麦 - t2
Java使用偏向锁定。这意味着获取锁的最后一个线程更有可能首先获得相同的锁。
答案 1 :(得分:0)
只有一个无用的实例,所以只有一个布尔值b。一旦设置为true,SleepMessages的两个实例都可以离开等待循环,无论哪一个都有机会运行,如果有多个CPU同时运行线程,则两者都会出现。
答案 2 :(得分:0)
当我测试你的代码时,两个线程都被中断而没有问题,所以我不确定为什么你认为其中任何一个没有进入catch块。
练习似乎是在第一次使用中断({触发线程打印其第一条消息)时从u1()
中的等待中断,并且第二次设置布尔b
(触发)第二条消息)。
对于interrupt()
,顺序是可以预测的,t1
将有足够的时间在主线程在中断之前的第二个睡眠中进行u1()
的下一次调用t2
。
对于u2()
部分,订单的可预测性要低得多。 t1
和t2
都在同一台监视器上等待。 notify()
电话可能会唤醒任何一个电话。醒来的那个打印出它的第二个消息,睡了一会儿然后停下来。第二个notify()
唤醒了在监视器上等待的一个线程。
所以最后两条消息的顺序是不确定的。
最后一些建议:您似乎想要实现的行为可能更容易使用CyclicBarrier
实现