全部博文(56)
分类: Java
2013-07-17 11:51:35
下面这段代码,主要功能是用两个线程来玩猜数字的游戏,第一线程负责随即给出一个1~100之间的随即整数,第二个线程负责猜出这个数字,每当第二个线程给出自己的猜测后,第一个线程都会提示“猜小了”“猜大了”“猜对了”
大家猜测一下,这段代码是否能完成预定功能,这段代码来源于Java2实用教程(第三版) |
public class Example9_6 { public static void main(String args[]) { Number number=new Number(); number.giveNumberThread.start(); number.guessNumberThread.start(); } } class Number implements Runnable { int realNumber,guessNumber,min=0,max=100,message; final int SMALLER=-1,LARGER=1,SUCCESS=8; Thread giveNumberThread,guessNumberThread; Number() { giveNumberThread=new Thread(this); guessNumberThread=new Thread(this); } public void run() { for(int count=1;true;count++) { if(Thread.currentThread()==giveNumberThread) { System.out.println("你第"+count+"次:");
if(count==1) { realNumber=(int)(Math.random()*100)+1; System.out.println("随机给你一个数,猜猜是多少?" + realNumber); } else { if(realNumber>guessNumber) { message=SMALLER; System.out.println("你猜小了"); } else if(realNumber<guessNumber) { message=LARGER; System.out.println("你猜大了"); } else { message=SUCCESS; System.out.println("恭喜,你猜对了"); return; } } try{ Thread.sleep(1500); } catch(Exception e){} } if(Thread.currentThread()==guessNumberThread) { System.out.println("我第"+count+"次:");
if(count==1) { guessNumber=(min+max)/2; System.out.println("我第"+count+"次猜这个数是:"+guessNumber ); } else { if(message==SMALLER) { min=guessNumber; guessNumber=(min+max)/2; System.out.println("我第"+count+"次猜这个数是:"+guessNumber +" min= " +min +" max= "+ max); } else if(message==LARGER) { max=guessNumber; guessNumber=(min+max)/2; System.out.println("我第"+count+"次猜这个数是:"+guessNumber +" max= "+ max +" min= " +min); } else if(message==SUCCESS) { System.out.println("我成功了!"); return; } } try{ Thread.sleep(1500); } catch(Exception e){} } } } }
|
实际运行中,发现这段代码,运行不稳定,偶尔出现问题,下面是其中出现的一次问题 |
你第1次: 我第1次: 我第1次猜这个数是:50 //线程你,还没有执行完,就被线程体我打断 随机给你一个数,猜猜是多少?42 你第2次: 你猜大了 我第2次: 我第2次猜这个数是:25 max= 50 min= 0 我第3次: 我第3次猜这个数是:12 max= 25 min= 0 //问题出现了,线程体我给出第二次数后,线程体 你第3次: //你没有作出判断,线程体我又被执行一次,而判断结果,却用了上一次, 你猜小了 //导致出错了 你第4次: 你猜小了 我第4次: 我第4次猜这个数是:18 min= 12 max= 25 你第5次: 你猜小了 我第5次: 我第5次猜这个数是:21 min= 18 max= 25 我第6次: 你第6次: 你猜小了 我第6次猜这个数是:23 min= 21 max= 25 你第7次: 你猜小了 我第7次: 我第7次猜这个数是:24 min= 23 max= 25 我第8次: 你第8次: 你猜小了 我第8次猜这个数是:24 min= 24 max= 25 你第9次: 你猜小了 我第9次: 我第9次猜这个数是:24 min= 24 max= 25 我第10次: 我第10次猜这个数是:24 min= 24 max= 25 你第10次: 你猜小了 你第11次: 你猜小了 我第11次: 我第11次猜这个数是:24 min= 24 max= 25 你第12次: 你猜小了 我第12次: 我第12次猜这个数是:24 min= 24 max= 25 |
//针对上面的问题,做了如下修改,先加入线程同步, synchronized(this){} 再加入线程控制, notifyAll(); try { wait(); // } catch(InterruptedException e){}
|
package Example9_61;
public class Example9_61 { public static void main(String args[]) { Number number=new Number(); number.giveNumberThread.start(); number.guessNumberThread.start(); } } class Number implements Runnable { int realNumber,guessNumber,min=0,max=100,message; final int SMALLER=-1,LARGER=1,SUCCESS=8; Thread giveNumberThread,guessNumberThread; Number() { giveNumberThread=new Thread(this); guessNumberThread=new Thread(this); } public void run() { synchronized(this){ for(int count=1;true;count++) { if(Thread.currentThread()==giveNumberThread) { System.out.println("你第"+count+"次:");
if(count==1) { realNumber=(int)(Math.random()*100)+1; System.out.println("随机给你一个数,猜猜是多少?" + realNumber); } else { if(realNumber>guessNumber) { message=SMALLER; System.out.println("你猜小了"); } else if(realNumber<guessNumber) { message=LARGER; System.out.println("你猜大了"); } else { message=SUCCESS; System.out.println("恭喜,你猜对了"); return; } } notifyAll(); try { wait(); //如果使用该方法的线程传递的参数是20须等待 } catch(InterruptedException e){}
} if(Thread.currentThread()==guessNumberThread) { System.out.println("我第"+count+"次:");
if(count==1) { guessNumber=(min+max)/2; System.out.println("我第"+count+"次猜这个数是:"+guessNumber ); } else { if(message==SMALLER) { min=guessNumber; guessNumber=(min+max)/2; System.out.println("我第"+count+"次猜这个数是:"+guessNumber +" min= " +min +" max= "+ max); } else if(message==LARGER) { max=guessNumber; guessNumber=(min+max)/2; System.out.println("我第"+count+"次猜这个数是:"+guessNumber +" max= "+ max +" min= " +min); } else if(message==SUCCESS) { System.out.println("我成功了!"); return; } } notifyAll();
try { wait(); //如果使用该方法的线程传递的参数是20须等待 } catch(InterruptedException e){}
} } } } }
|
你第1次: 随机给你一个数,猜猜是多少?33 我第1次: 我第1次猜这个数是:50 你第2次: 你猜大了 我第2次: 我第2次猜这个数是:25 max= 50 min= 0 你第3次: 你猜小了 我第3次: 我第3次猜这个数是:37 min= 25 max= 50 你第4次: 你猜大了 我第4次: 我第4次猜这个数是:31 max= 37 min= 25 你第5次: 你猜小了 我第5次: 我第5次猜这个数是:34 min= 31 max= 37 你第6次: 你猜大了 我第6次: 我第6次猜这个数是:32 max= 34 min= 31 你第7次: 你猜小了 我第7次: 我第7次猜这个数是:33 min= 32 max= 34 你第8次: 恭喜,你猜对了 |
保证一次线程体执行过程不被打断,同时能等待其它线程执行 |