【ThinkingInJava】63、哲学家进餐问题

来源:互联网 发布:淘宝什么时间上下架好 编辑:程序博客网 时间:2024/05/17 05:06

/*** 书本:《Thinking In Java》* 功能:哲学家进餐问题* 作为哲学家,他们很穷,所以他们只能买五根筷子。他们围坐在桌子周围,每人之间放一根筷子。当一个哲学家要就餐的时候了,这个哲学家必须同时得到左边* 和右边的筷子。如果一个哲学家左边或右边的筷子已经有人在使用筷子了,那么这个哲学家就必须等待,直至可以得到必须的筷子* 文件:Chopstick.java* 时间:2015年5月9日15:08:21* 作者:cutter_point*/package Lesson21Concurency;public class Chopstick{private boolean taken = false;//筷子是否已经被拿起来了public synchronized void take() throws InterruptedException{while(taken)this.wait();  //如果筷子被拿起来了,那么就得等待,等待其他进程对他进行唤醒taken = true; //如果没有拿起来,那么调用这个函数筷子被取起来了}public synchronized void drop()//这个函数是放下筷子{taken = false;this.notifyAll(); //唤醒别人,这个筷子又可以使用了}}

/*** 书本:《Thinking In Java》* 功能:哲学家进餐问题* 作为哲学家,他们很穷,所以他们只能买五根筷子。他们围坐在桌子周围,每人之间放一根筷子。当一个哲学家要就餐的时候了,这个哲学家必须同时得到左边* 和右边的筷子。如果一个哲学家左边或右边的筷子已经有人在使用筷子了,那么这个哲学家就必须等待,直至可以得到必须的筷子* 文件:Philosopher.java* 时间:2015年5月9日15:17:36* 作者:cutter_point*/package Lesson21Concurency;import java.util.Random;import java.util.concurrent.TimeUnit;import static net.mindview.util.Print.*;public class Philosopher implements Runnable//一个哲学家线程{//哲学家左右两边有两双筷子,这名哲学家得id号,给一个数据,用来判断哲学家是思考还是进餐private Chopstick left;//左筷子private Chopstick right;//右筷子private final int id;//这名哲学家得id号private final int ponderFactor; //一个数据用来判定是否会思考还是进餐private Random rand = new Random(998);public Philosopher(Chopstick left, Chopstick right, int ident, int ponder){this.left = left;this.right = right;this.id = ident;//哲学家的id号码this.ponderFactor = ponder; //哲学家思考数据}private void pause() throws InterruptedException{if(this.ponderFactor == 0){//如果哲学家得思考数据是0的话,那么就不用暂停思考了,直接返回return;}//如果哲学家要思考的话,那么我们就要让他暂停一段时间TimeUnit.MILLISECONDS.sleep(rand.nextInt(this.ponderFactor * 1500)); //思考时间}public String toString(){return "哲学家:" + this.id + " 号 ";}@Overridepublic void run(){//哲学家的行动模式//收先,如果哲学家还在餐桌上,也就是没有被中断try{while(!Thread.interrupted()){//1、首先哲学家会思考print(this + " " + " 在思考");this.pause(); //思考一段时间//2、思考一段时间后觉得饿了,那么哲学家就要进餐了,那么就会拿起来左边和右边的筷子,然后开始进餐,进餐额时间又会有一段this.right.take(); //拿起筷子print(this + " " + "拿起右边的筷子");this.left.take();print(this + " " + "拿起左边的筷子");print(this + " " + "开始吃饭");this.pause(); //吃饭花的时间//3、吃完之后就会放下左右的筷子print(this + " " + "吃完了,放下筷子");this.left.drop();this.right.drop();}} catch (InterruptedException e){e.printStackTrace();print(this + " " + " 被中断了退出了餐桌。");}}}

/*** 书本:《Thinking In Java》* 功能:哲学家进餐问题* 作为哲学家,他们很穷,所以他们只能买五根筷子。他们围坐在桌子周围,每人之间放一根筷子。当一个哲学家要就餐的时候了,这个哲学家必须同时得到左边* 和右边的筷子。如果一个哲学家左边或右边的筷子已经有人在使用筷子了,那么这个哲学家就必须等待,直至可以得到必须的筷子* 文件:DeadlockingDiningPhilosophers.java* 时间:2015年5月9日15:36:13* 作者:cutter_point*/package Lesson21Concurency;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;public class DeadlockingDiningPhilosophers{public static void main(String[] args) throws Exception{int ponder = 5;int size = 5;//哲学家得ExecutorService exec = Executors.newCachedThreadPool(); //线程连接池Chopstick[] sticks = new Chopstick[size];//创建数组空间for(int i = 0; i < size; ++i)sticks[i] = new Chopstick();//初始化数组里面的对象for(int i = 0; i < size; ++i){exec.execute(new Philosopher(sticks[i], sticks[(i+1) % size], i, ponder));}if(args.length == 3 && args[2].equals("timeout"))TimeUnit.SECONDS.sleep(5);else{System.out.println("回车键退出");System.in.read();}exec.shutdownNow();//停止全部线程}}

输出:
回车键退出
哲学家:4 号   在思考  obj1
哲学家:1 号   在思考  obj1
哲学家:3 号   在思考  obj1
哲学家:2 号   在思考  obj1
哲学家:0 号   在思考  obj1
哲学家:3 号  拿起右边的筷子  obj1
哲学家:2 号  拿起右边的筷子  obj1
哲学家:1 号  拿起右边的筷子  obj1
哲学家:0 号  拿起右边的筷子  obj1
哲学家:4 号  拿起右边的筷子  obj1

java.lang.InterruptedException
哲学家:3 号   被中断了退出了餐桌。  obj1
哲学家:0 号   被中断了退出了餐桌。  obj1
哲学家:1 号   被中断了退出了餐桌。  obj1
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:503)
    at Lesson21Concurency.Chopstick.take(Chopstick.java:18)
    at Lesson21Concurency.Philosopher.run(Philosopher.java:65)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
java.lang.InterruptedException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:503)
    at Lesson21Concurency.Chopstick.take(Chopstick.java:18)
    at Lesson21Concurency.Philosopher.run(Philosopher.java:65)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
java.lang.InterruptedException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:503)
    at Lesson21Concurency.Chopstick.take(Chopstick.java:18)
    at Lesson21Concurency.Philosopher.run(Philosopher.java:65)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
java.lang.InterruptedException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:503)
    at Lesson21Concurency.Chopstick.take(Chopstick.java:18)
    at Lesson21Concurency.Philosopher.run(Philosopher.java:65)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
哲学家:2 号   被中断了退出了餐桌。  obj1
java.lang.InterruptedException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:503)
    at Lesson21Concurency.Chopstick.take(Chopstick.java:18)
    at Lesson21Concurency.Philosopher.run(Philosopher.java:65)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
哲学家:4 号   被中断了退出了餐桌。  obj1




这个会导致死锁,也就是共享的有限资源不够,被多个线程争抢的时候的情况


改进:

/*** 书本:《Thinking In Java》* 功能:哲学家进餐问题* 作为哲学家,他们很穷,所以他们只能买五根筷子。他们围坐在桌子周围,每人之间放一根筷子。当一个哲学家要就餐的时候了,这个哲学家必须同时得到左边* 和右边的筷子。如果一个哲学家左边或右边的筷子已经有人在使用筷子了,那么这个哲学家就必须等待,直至可以得到必须的筷子* 文件:FixedDiningPhilosophers.java* 时间:2015年5月9日15:36:13* 作者:cutter_point*/package Lesson21Concurency;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;public class FixedDiningPhilosophers{public static void main(String[] args) throws Exception{int ponder = 5;int size = 5;//哲学家得ExecutorService exec = Executors.newCachedThreadPool(); //线程连接池Chopstick[] sticks = new Chopstick[size];//创建数组空间for(int i = 0; i < size; ++i)sticks[i] = new Chopstick();//初始化数组里面的对象for(int i = 0; i < size; ++i){//exec.execute(new Philosopher(sticks[i], sticks[(i+1) % size], i, ponder));if(i < (size - 1))exec.execute(new Philosopher(sticks[0], sticks[i+1], i, ponder));elseexec.execute(new Philosopher(sticks[0], sticks[i], i, ponder));}if(args.length == 3 && args[2].equals("timeout"))TimeUnit.SECONDS.sleep(5);else{System.out.println("回车键退出");System.in.read();}exec.shutdownNow();//停止全部线程}}

输出:

回车键退出
哲学家:2 号   在思考  obj1
哲学家:0 号   在思考  obj1
哲学家:4 号   在思考  obj1
哲学家:1 号   在思考  obj1
哲学家:3 号   在思考  obj1
哲学家:2 号  拿起右边的筷子  obj1
哲学家:2 号  拿起左边的筷子  obj1
哲学家:2 号  开始吃饭  obj1
哲学家:4 号  拿起右边的筷子  obj1
哲学家:1 号  拿起右边的筷子  obj1
哲学家:0 号  拿起右边的筷子  obj1
哲学家:2 号  吃完了,放下筷子  obj1
哲学家:2 号   在思考  obj1
哲学家:0 号  拿起左边的筷子  obj1
哲学家:0 号  开始吃饭  obj1
哲学家:0 号  吃完了,放下筷子  obj1
哲学家:0 号   在思考  obj1
哲学家:4 号  拿起左边的筷子  obj1
哲学家:4 号  开始吃饭  obj1
哲学家:4 号  吃完了,放下筷子  obj1
哲学家:4 号   在思考  obj1
哲学家:1 号  拿起左边的筷子  obj1
哲学家:3 号  拿起右边的筷子  obj1
哲学家:1 号  开始吃饭  obj1
哲学家:1 号  吃完了,放下筷子  obj1
哲学家:1 号   在思考  obj1
哲学家:3 号  拿起左边的筷子  obj1
哲学家:3 号  开始吃饭  obj1
哲学家:3 号  吃完了,放下筷子  obj1
哲学家:3 号   在思考  obj1
哲学家:2 号  拿起右边的筷子  obj1
哲学家:2 号  拿起左边的筷子  obj1
哲学家:2 号  开始吃饭  obj1
哲学家:0 号  拿起右边的筷子  obj1
哲学家:4 号  拿起右边的筷子  obj1
哲学家:1 号  拿起右边的筷子  obj1
哲学家:2 号  吃完了,放下筷子  obj1
哲学家:2 号   在思考  obj1
哲学家:1 号  拿起左边的筷子  obj1
哲学家:1 号  开始吃饭  obj1
哲学家:2 号  拿起右边的筷子  obj1
哲学家:1 号  吃完了,放下筷子  obj1
哲学家:1 号   在思考  obj1
哲学家:2 号  拿起左边的筷子  obj1
哲学家:2 号  开始吃饭  obj1
哲学家:1 号  拿起右边的筷子  obj1
哲学家:2 号  吃完了,放下筷子  obj1
哲学家:2 号   在思考  obj1
哲学家:1 号  拿起左边的筷子  obj1
哲学家:1 号  开始吃饭  obj1
哲学家:2 号  拿起右边的筷子  obj1
哲学家:1 号  吃完了,放下筷子  obj1
哲学家:1 号   在思考  obj1
哲学家:2 号  拿起左边的筷子  obj1
哲学家:2 号  开始吃饭  obj1
哲学家:1 号  拿起右边的筷子  obj1

java.lang.InterruptedException
哲学家:3 号   被中断了退出了餐桌。  obj1
哲学家:0 号   被中断了退出了餐桌。  obj1
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:503)
    at Lesson21Concurency.Chopstick.take(Chopstick.java:18)
    at Lesson21Concurency.Philosopher.run(Philosopher.java:63)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
java.lang.InterruptedException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:503)
    at Lesson21Concurency.Chopstick.take(Chopstick.java:18)
    at Lesson21Concurency.Philosopher.run(Philosopher.java:65)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at java.lang.Thread.sleep(Thread.java:340)
    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:360)
    at Lesson21Concurency.Philosopher.pause(Philosopher.java:42)
    at Lesson21Concurency.Philosopher.run(Philosopher.java:68)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
哲学家:2 号   被中断了退出了餐桌。  obj1
java.lang.InterruptedException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:503)
    at Lesson21Concurency.Chopstick.take(Chopstick.java:18)
    at Lesson21Concurency.Philosopher.run(Philosopher.java:65)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
java.lang.InterruptedException哲学家:4 号   被中断了退出了餐桌。  obj1

    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:503)
    at Lesson21Concurency.Chopstick.take(Chopstick.java:18)
    at Lesson21Concurency.Philosopher.run(Philosopher.java:65)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
哲学家:1 号   被中断了退出了餐桌。  obj1

这个不会死锁,只要当你回车的时候才会结束各个线程之间的配合






































0 0
原创粉丝点击