/** * 书本:《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 + " 号 "; } @Override public 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)); else exec.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
这个不会死锁,只要当你回车的时候才会结束各个线程之间的配合