我有两套代码,我试图依次打印字母和数字。一套使用“ while循环”,另一套使用“ if”。
public class Alphabets {
public static void main(String[] args) {
AN an= new AN(false);
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
try {
an.Alpha();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread t2= new Thread(new Runnable() {
@Override
public void run() {
try {
an.numbers();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t1.start();
t2.start();
}
}
class AN {
boolean flag;
AN(boolean flag) {
this.flag=flag;
}
synchronized void Alpha() throws InterruptedException {
for(char i='A'; i<='Z';i++) {
while(flag==false) { // I have replaced "while" with "if" in my second code
System.out.println(+i);
notifyAll();
flag=true;
}
wait();
}
}
synchronized void numbers() throws InterruptedException {
for(int i=1;i<=26;i++) {
while(flag==true) {// I have replaced "while" with "if" in my second code
System.out.println(+i);
notifyAll();
flag=false;
}
wait();
}
}
}
通过“ while”循环设置1给出以下输出:
65 1 66 2 67 3 68 4
将2设置为“ if”可得到以下输出:
65 1 67 3 69 5 71 7
请注意,65 66是A,B等的ASCII码。
任何人都可以解释为什么这两个代码是这样的。我无法弄清楚。 请详细解释。
答案 0 :(得分:0)
答案在spurious wakeup中。这意味着在没有任何人实际调用notify的情况下,任何等待语句都可能自发地唤醒。在这种情况下,for循环又前进了一步,而实际上没有打印任何内容,因为该标志仍处于错误状态。
使用或是否对代码本身没有影响,只是碰巧更频繁地触发实际问题。
解决此问题的方法是循环等待,直到状态实际更改:
for(char i='A'; i<='Z';i++) {
if(flag==false) {
System.out.println(+i);
notifyAll();
flag=true;
}
while (flag == true) { // spurious wakeup prevention
wait();
}
}
答案 1 :(得分:-1)
while loop
在多线程中是首选,因为它可以防止 spurious wake up
,这意味着wait()方法可以在没有用户线程通知的情况下返回,可能是由 OS scheduler
完成的。在您的情况下,我猜因为spurious wakeup
if() condition
被跳过,然后又转到wait()
。