读书人

Java实现哲学家进餐线程调度出现有关

发布时间: 2012-02-11 09:51:35 作者: rapoo

Java实现哲学家进餐,线程调度出现问题,求指点!


package com.java.mythread;

/**
* 哲学家进餐问题的解决
* 缺点:线程调度不是先进先出调度或优先级调度
* */
public class Dining {
public static void main(String[] args){
Chopstick[] chops = new Chopstick[5];
Philosopher[] philos= new Philosopher[5];
for(int i= 0;i<5;i++){
chops[i] = new Chopstick();
}
for(int i= 0;i<5;i++){
philos[i] = new Philosopher(i,chops[i],chops[(i+1)%5]);
}

for(int i= 0;i<5;i++){
philos[i].start();
}
}
}

class Chopstick{
private boolean available;
public Chopstick(){
available = true;
}
public void takeUp(){
available = false;
}
public void putDown(){
available = true;
}
public boolean getStatus(){
return available;
}
}

class Philosopher extends Thread{
public static int eatTime = 200, thinkTime = 300;
private Chopstick left,right;
int philo_num;
public Philosopher(int No,Chopstick lc,Chopstick rc){
left = lc;
right = rc;
philo_num = No;
//setDaemon(true);
}
synchronized public void requestChops(){
while(!left.getStatus() || !right.getStatus()){
System.out.println("哲学家"+philo_num+"正在等待……");
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
left.takeUp();
right.takeUp();
}
synchronized public void returnChops(){
left.putDown();
right.putDown();
notify();
}
public void eat(){
System.out.println("哲学家"+philo_num+"正在进餐……");
try{
sleep(eatTime);
}catch(Exception e){}
}
public void think(){
System.out.println("哲学家"+philo_num+"正在思考……");
try{
sleep(thinkTime);
}catch(Exception e){}
}
public void run(){
while(true){
this.think();
this.requestChops();
this.eat();
this.returnChops();
}
}
}

最后运行结果是:
哲学家0正在思考……
哲学家3正在思考……
哲学家2正在思考……
哲学家1正在思考……
哲学家4正在思考……
哲学家0正在等待……
哲学家4正在进餐……
哲学家3正在等待……
哲学家1正在等待……
哲学家2正在进餐……
哲学家4正在思考……
哲学家2正在思考……
哲学家4正在进餐……
哲学家2正在进餐……
无论等多长时间,只有哲学家2和哲学家4线程在运行,这掌握很费解啊。
代码中当某哲学家进餐完毕,执行this.returnChops();操作时,调用notify()函数后,不是所有等待进程同时竞争资源吗?为什么会只有两个线程一直运行,其他线程出于饥饿状态?改成notifyAll()函数,结果也一样。
哪位能给下指点啊?


















[解决办法]
没格式化没着色真难看

Java code
package com.java.mythread;/** * 哲学家进餐问题的解决 * 缺点:线程调度不是先进先出调度或优先级调度 * */public class Dining {public static void main(String[] args){Chopstick[] chops = new Chopstick[5];Philosopher[] philos= new Philosopher[5];for(int i= 0;i<5;i++){chops[i] = new Chopstick();}for(int i= 0;i<5;i++){philos[i] = new Philosopher(i,chops[i],chops[(i+1)%5]);}for(int i= 0;i<5;i++){philos[i].start();}}}class Chopstick{private boolean available;public Chopstick(){available = true;}public void takeUp(){available = false;}public void putDown(){available = true;}public boolean getStatus(){return available;}}class Philosopher extends Thread{public static int eatTime = 200, thinkTime = 300;  private Chopstick left,right;int philo_num;public Philosopher(int No,Chopstick lc,Chopstick rc){left = lc;right = rc;philo_num = No;//setDaemon(true);}synchronized public void requestChops(){while(!left.getStatus() || !right.getStatus()){System.out.println("哲学家"+philo_num+"正在等待……");try {wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}left.takeUp();right.takeUp();}synchronized public void returnChops(){left.putDown();right.putDown();notify();}public void eat(){System.out.println("哲学家"+philo_num+"正在进餐……");try{sleep(eatTime);}catch(Exception e){}}public void think(){System.out.println("哲学家"+philo_num+"正在思考……");try{sleep(thinkTime);}catch(Exception e){}}public void run(){while(true){this.think();this.requestChops();this.eat();this.returnChops();}}} 


[解决办法]
LZ对同步概念模糊
要知道,多个线程同时使用相同的资源才有同步问题
你这里的5个线程各自调用自己的方法
this.think();
this.requestChops();
this.eat();
this.returnChops();
跟线程和线程之间没有锁住同一个资源,你的wait和notify根本就没意义,只是自己对自己wait和notify,所以一旦进入wait,就一直等待不会被唤醒,就好像LZ的打印结果0和3,后面应该不会再出现0和3的任何打印了,因为一直停留在等待中了

多个线程锁某个资源,应该synchronize(资源),然后调用 资源.wait() 资源.notify() 来达到等待和唤醒,或者在资源的方法上加上synchronized,这样wait或notify缺省就是资源的this.wait this.notify,这样才能达到同步的效果

LZ再好好想想吧

[解决办法]
楼主正在学操作系统?
看书慢慢写吧
[解决办法]
不会出现两个线程同时访问资源.
一位哲学家(假设1号)就餐时(访问资源),其前后两位(2和5) 因得不到筷子,会在"对象wait 池"里阻塞,另两位中的一位(假设3)能得到筷子,但不能得到同步锁,是在"对象lock池阻塞".(4号与2和5一样). 3号要等到1号释放锁后,才会进入就绪状态,可以运行.
此时2号或5号有一位会被 notify()唤醒,而进入对象lock 池. 一旦得到同步锁,即可运行(去吃饭).

读书人网 >J2SE开发

热点推荐