哲学家用餐问题的疑问?

//筷子
class Chopstick {
private boolean taken;// 是否被拿起

public synchronized void take() {
// ....
}

public synchronized void drop() {
// ...
}
}

// 哲学家
class Philosopher implements Runnable {
private Chopstick leftChopstick; // 左筷子
private Chopstick rightChopstick;// 右筷子

public Philosopher(Chopstick leftChopstick, Chopstick rightChopstick) {
// 初始化筷子及相关的东东
// ...
}

public void run() {
// 拿起左筷子,拿起右筷子
// ...
}
}

/**
* 死锁的哲学家模拟
* @author Administrator
*/
public class DeadlockingDiningPhilosopher {

/**
* @param args
*/
public static void main(String[] args) {
// 五个哲学家,五个筷子,
}

}
在java编程思想中, 有如上筷子和哲学家, 其行为如上所示, 我要看这程序的时候有点疑问, 很有时候也有这个疑问, 取筷子和放筷子是哲学家的行为, 为什么放置到了筷子对象的身上, 在其它的很时候也感觉到对行为该放置到哪里产生疑问? 有人也有此疑问吗?

private boolean taken;// 是否被拿起

sth. be taken .... 表示 sth.被拿起或被拿走 的意思啊.
这样就很明显了,,,,是被动的,,,,这样可以说的通吧....那也就OK吧...


不知道我说的对不对.初学java.

>在其它的很时候也感觉到对行为该放置到哪里产生疑问
非常好,你这个疑问正好击中Java编程思想 Thinking in Java TIJ的弱点。
TIJ重点展示你Java结果,而不是告诉你如何得到这些结果,如何得到这些结果就是设计思维过程,这才是真正编程思想。

从业务建模方面看,筷子不能自己拿起自己,所以,拿起行为放在筷子对象中是不合适的,不过,这不是TIJ在这里重点,这是进一步的高要求的,对于tij告诉你Java可以这么做就行了。


若是行为放在筷子里面不合适, 那么如果将行为放置到哲学家身上
class Philosopher implements Runnable {
public void tokenLeft() { //拿起左筷子
synchronized (leftChopstick) {
if (左筷子未被起)
左筷子.wait();
将左筷子置为拿起
}
}
//拿起右筷子.....
}
那么根据Martin Fowler的重构,这个方法所操纵到的东东只与筷子有关,而与哲学家无关,因此,其可被重构移动到筷子对象的身上,
重构中讲究以对象来替代标记量, 即可以由筷子派生出 拿起的筷子,放下的筷子, 但是由于筷子处于临界区,被多个线程访问, 因此其用对象来替换掉标志量taken, 则又会比较的麻烦.
Think in java中说线程来自过程化的产物, 感觉在这里用面向对象很是别扭.

这其实是一个不伦不类的例子。

业务对象应该和技术无关,但是这里将业务对象和线程这样一个具体技术耦合捆绑在一起,几乎没有实用价值,而且会误导初学者。以为所谓编程思想:就是如何将业务和具体技术捣浆糊捣在一起,就体现思想了。

>行为放在筷子里面不合适, 那么如果将行为放置到哲学家身上
也不能放在哲学家身上,因为哲学家不是成天拿筷子放筷子,这不是其本质天然行为,只是在当前这个筷子的业务场景才会发生筷子的行为。这里可以用桥模式解决,哲学家有一个抽象行为动作,这个行为动作在当前场景是拿放筷子这个具体实现,在当前场景也是用线程实现。

仅供参考

哈哈, 谢谢banq大哥的回复, 先把书看完再说, 不管怎么说从TIJ中学习到很多java的用法.看完书后,再学一下JDON.哈哈!