/**
* 书本:《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
这个不会死锁,只要当你回车的时候才会结束各个线程之间的配合