刚看过java线程,于是尝试着模拟一下经典的哲学家就餐问题。
总是看别人的还是不行,自己动手,收获要多一些。
下面这个最终结果,修改过几次。
比如关于wait()调用,开始没注意到调用它会释放监视器,然后发现了。又想查一下jdk文档确认,诧异地发现没有释放监视器的说明。再仔细看一遍,原来是中文版把release错误地翻译成了发布...应该是释放
还有是死锁:开始的版本会发生5个人都拿起了左手的叉子...
后来改成如果拿右边叉子失败,释放左手的,不断重试
sleep函数也很重要,否则虽然运行正确,结果却很怪异
class Fork
{
private boolean lockon;
public Fork(){ lockon = false; }
public boolean isLocked()
{
return lockon == true;
}
public synchronized void Lock()
{
while (lockon == true)
{
try
{
wait();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
lockon = true;
}
public synchronized void unLock()
{
lockon = false;
notifyAll();
}
}
class Philo extends Thread
{
private char name; //哲学家的名字:A B C D E
private static Fork[] forks = new Fork[5];//共用5根叉子
private Fork left;
private Fork right;
static
{
for (int i=0; i<5; i++)
{
forks[i] = new Fork();
}
}
public Philo(int i)
{
left = forks[i];
right = forks[(i+1)%5];
}
public void setMyName (char name)
{
this.name = name;
}
public char getMyName ()
{
return this.name;
}
public void getLeftFork()
{
left.Lock();
}
public boolean getRightFork() //确保拿了左筷子才拿右筷子,右不可拿则释放左筷子
{
if ( right.isLocked()) //破坏死锁四大条件之一:占有且等待
{
left.unLock();
System.out.println(getMyName()+" put left fork");
return false;
}
else
{
right.Lock();
return true;
}
}
public void putLeftFork()
{
left.unLock();
}
public void putRightFork()
{
right.unLock();
}
public void run()
{
while(true)
{
boolean succ = false;
System.out.println(getMyName()+" is thinking");
while (succ != true)
{
getLeftFork();
System.out.println(getMyName()+" get left fork");
if(getRightFork())
{
succ = true;
System.out.println(getMyName()+" get right fork");
}
try{
Thread.sleep((long)(Math.random()*1000));
}catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(getMyName()+" is eating");
try{
Thread.sleep((long)(Math.random()*2000));
}catch (InterruptedException e) {
e.printStackTrace();
}
putRightFork();
putLeftFork();
System.out.println(getMyName()+" eaten done!");
}
}
}
public class runPhilo
{
public static void main( String[] args )
{
Philo[] philosopher = new Philo[5];
char ch = 'A';
for ( int i=0; i<5; i++)
{
philosopher[i] = new Philo(i);
philosopher[i].setMyName(ch++);
}
for (int i=0; i<5; i++)
{
philosopher[i].start();
}
System.out.println("Main thread is running");
}
}
