notify和notifyAll

kevinwangxiyu 2012-04-29 01:44:14
代码如下:
public class Philosopher {
public static void main(String [] args){
ChopStick chopstick_1=new ChopStick("1号筷子");
ChopStick chopstick_2=new ChopStick("2号筷子");
ChopStick chopstick_3=new ChopStick("3号筷子");
ChopStick chopstick_4=new ChopStick("4号筷子");
Philosopher_Using pu_1=new Philosopher_Using("哲学家_1",chopstick_1,chopstick_2);
Philosopher_Using pu_2=new Philosopher_Using("哲学家_2",chopstick_2,chopstick_3);
Philosopher_Using pu_3=new Philosopher_Using("哲学家_3",chopstick_3,chopstick_4);
Philosopher_Using pu_4=new Philosopher_Using("哲学家_4",chopstick_4,chopstick_1);
Thread tpu_1=new Thread(pu_1);
Thread tpu_2=new Thread(pu_2);
Thread tpu_3=new Thread(pu_3);
Thread tpu_4=new Thread(pu_4);
tpu_1.start();
tpu_2.start();
tpu_3.start();
tpu_4.start();

}
}
class ChopStick{
protected String chopName;
private boolean available=true;
public ChopStick(String name){
chopName=name;
}
public void getChopStick(){
synchronized(this){
try{
while(available!=true){
this.wait();
}
available=false;
}catch(Exception e){
System.out.println("ERROR!");

}

}
}
public void releaseChopStick(){
synchronized(this){
available=true;
notify();
}
}
public void thinking(String name){
System.out.println(name+"is thinking");


}
public void eatMeal(String name){
System.out.println(name+"is eating");
}

}
class Philosopher_Using implements Runnable{
private String p_name;
ChopStick stickLeft;
ChopStick stickRight;
public Philosopher_Using(String name,ChopStick stickLeft,ChopStick stickRight){
p_name=name;
this.stickLeft=stickLeft;
this.stickRight=stickRight;
}
public void run(){
stickLeft.thinking(p_name);
try{
Thread.currentThread();
Thread.sleep(500);
}catch(Exception e){};
stickLeft.getChopStick();
System.out.println(p_name+"抓起了"+stickLeft.chopName);
stickRight.getChopStick();
System.out.println(p_name+"抓起了"+stickRight.chopName);
stickRight.eatMeal(p_name);
try{
Thread.currentThread();
Thread.sleep(500);
}catch(Exception e){};
stickLeft.releaseChopStick();
System.out.println(p_name+"放下了"+stickLeft.chopName);
stickRight.releaseChopStick();
System.out.println(p_name+"放下了"+stickRight.chopName);
}
}

输出结果:
哲学家_1is thinking
哲学家_4is thinking
哲学家_3is thinking
哲学家_2is thinking
哲学家_1抓起了1号筷子
哲学家_1抓起了2号筷子
哲学家_1is eating
哲学家_3抓起了3号筷子
哲学家_4抓起了4号筷子
哲学家_1放下了1号筷子
哲学家_4抓起了1号筷子
哲学家_4is eating
哲学家_2抓起了2号筷子
哲学家_1放下了2号筷子

哲学家_4放下了4号筷子
哲学家_3抓起了4号筷子
哲学家_3is eating
哲学家_4放下了1号筷子
哲学家_3放下了3号筷子
哲学家_2抓起了3号筷子
哲学家_3放下了4号筷子
哲学家_2is eating
哲学家_2放下了2号筷子
哲学家_2放下了3号筷子

用notify的时候总会有这样的异常现象。还没放下筷子,就会先抓起。是什么原因呢?
改notifyAll的话倒是正常的。不知道两者区别在哪里?
...全文
153 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
kevinwangxiyu 2012-04-29
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

线程的输出优先是由JVM自行决定无法很精确的控制
[/Quote]
学习了!
kevinwangxiyu 2012-04-29
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

比如说“哲学家_2”这个线程比“哲学家_1”这个线程优先级高很多,因此速度快很多。当“哲学家_1”释放掉2号筷子还没来得及打印“哲学家_1放下了2号筷子”这句话的时候,“哲学家_2”这个线程就已经获得了2号筷子,并且打印出来了“哲学家_2抓起了2号筷子”。因此造成了这种假象。
至于为什么换成notifyAll就变得正常,可以假设“哲学家_3”这个线程优先级非常高,高于其它所有线程,并且他正在等……
[/Quote]
好的 谢谢你的解释。
我也知道每次不同,但是就是好奇为什么使用notifyAll就正常,而notify就会有这问题。
就想知道其中的不同。
宁波朱超 2012-04-29
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

线程的输出优先是由JVM自行决定无法很精确的控制
[/Quote]

+1

正因如此 每次执行的结果 都会不同 每台服务器的执行也不会同。
cscxxx 2012-04-29
  • 打赏
  • 举报
回复
线程的输出优先是由JVM自行决定无法很精确的控制
cryingzgz 2012-04-29
  • 打赏
  • 举报
回复
比如说“哲学家_2”这个线程比“哲学家_1”这个线程优先级高很多,因此速度快很多。当“哲学家_1”释放掉2号筷子还没来得及打印“哲学家_1放下了2号筷子”这句话的时候,“哲学家_2”这个线程就已经获得了2号筷子,并且打印出来了“哲学家_2抓起了2号筷子”。因此造成了这种假象。
至于为什么换成notifyAll就变得正常,可以假设“哲学家_3”这个线程优先级非常高,高于其它所有线程,并且他正在等待某一个筷子。所以当“哲学家_1”调用notifyAll()唤醒所有线程的时候,“哲学家_3”先执行,但没有符合条件的筷子,因此他继续等待。而“哲学家_2”任然处于等待状态。然后“哲学家_1”打印出“哲学家_1放下了2号筷子”。
线程这里主要考虑线程安全问题,不用太拘泥于输出结果,因为每次输出的结果都是不确定的。

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧