多线程--哲学家就餐问题
2015-07-05 20:06
337 查看
1、当哲学家的左右筷子均是可用的时候才能就餐,否则等待,很容易理解,一次最多能有两个人同时就餐
public class PhilosopherEating { private static Thread[] threads = new Thread[5]; public static void main(String[] args) { System.out.println("Hello World!"); for(int i = 0 ; i < 5; i ++){ threads[i] = new Thread(new Philosopher(i)); threads[i].start(); } //当前线程组活动线程数 while(Thread.activeCount()>1){ Chopstick.monitor(); try{ Thread.sleep(1000); }catch(InterruptedException ex){ } } } } /* * 哲学家进程 */ class Philosopher implements Runnable { //所有哲学家共用五支筷子 private static Chopstick chopstick = new Chopstick(); //哲学家编号 private int id = 0; public Philosopher(int id){ this.id = id; } public void run(){ while(true){ if(new Random().nextBoolean()){ //取筷子 chopstick.take(id); eat(); //放筷子 chopstick.down(id); }else{ think(); } } } //就餐 private void eat(){ int time = new Random().nextInt(10); try{ System.out.println(id + "就餐"+time+"s"); Thread.sleep(time*1000); System.out.println(id + "就餐完成!"); }catch(InterruptedException ex){ System.out.println("ex:eat"); } } //思考 private void think(){ int time = new Random().nextInt(10); try{ System.out.println(id + "思考"+time+"s"); Thread.sleep(time*1000); }catch(InterruptedException ex){ System.out.println("ex:think"); } } } /* * 筷子 * 作为资源 */ class Chopstick { private static Lock lock = new ReentrantLock(); private static Condition chopstick = lock.newCondition(); //五支筷子是否在使用 private static boolean[] used = new boolean[5]; //取筷子 public void take(int id){ //获取锁 lock.lock(); try{ //左筷子,右筷子可以使用 while(used[id] || used[(id+1)%5]){ chopstick.await(); } used[id] = true; used[(id+1)%5] = true; }catch(InterruptedException ex){ }finally{ //释放锁 lock.unlock(); } } //放筷子 public void down(int id){ lock.lock(); used[id] = false; used[(id+1)%5] = false; chopstick.signalAll(); lock.unlock(); } //监控是否发生死锁,如果所有的筷子都是使用状态,则说明死锁 public static boolean monitor(){ boolean flag = true; for(int i = 0 ; i < 5 ; i ++ ){ if(used[i] == false){ flag = false; break; } } return flag; } }
2、创建一个服务员,每次哲学家就餐都需要询问服务员
public class PhilosopherEating2 { private static Thread[] threads = new Thread[5]; public static void main(String[] args) { System.out.println("Hello World!"); for(int i = 0 ; i < 5; i ++){ threads[i] = new Thread(new Philosopher(i)); threads[i].start(); } //当前线程组活动线程数 while(Thread.activeCount()>1){ if(Waiter.monitor()){ System.out.println("死锁!!!!!!!!!!!!!!!!"); } try{ Thread.sleep(100); }catch(InterruptedException ex){ } } } } /* * 哲学家进程 */ class Philosopher implements Runnable { //服务员 private static Waiter waiter = new Waiter(); //哲学家编号 private int id = 0; public Philosopher(int id){ this.id = id; } public void run(){ while(true){ if(new Random().nextBoolean()){ if(waiter.ask(id)){ eat(); waiter.put(id); } }else{ think(); } } } //就餐 private void eat(){ int time = new Random().nextInt(10); try{ System.out.println(id + "就餐"+time+"s"); Thread.sleep(time*100); System.out.println(id + "就餐完成!"); }catch(InterruptedException ex){ System.out.println("ex:eat"); } } //思考 private void think(){ int time = new Random().nextInt(10); try{ System.out.println(id + "思考"+time+"s"); Thread.sleep(time*100); }catch(InterruptedException ex){ System.out.println("ex:think"); } } } /* * 服务员 */ class Waiter { //五支筷子是否在使用 private static boolean[] used = new boolean[5]; //询问是否可以就餐 public synchronized boolean ask(int id){ if(used[id] || used[(id+1)%5]){ return false; } used[id] = true; used[(id+1)%5] = true; return true; } //交筷子 public synchronized void put(int id){ used[id] = false; used[(id+1)%5] = false; } //监控是否发生死锁,如果所有的筷子都是使用状态,则说明死锁 public static boolean monitor(){ boolean flag = true; for(int i = 0 ; i < 5 ; i ++ ){ if(used[i] == false){ flag = false; break; } } return flag; } }
3、使用信号量,每个哲学家只能先申请大号筷子,然后再申请小号筷子,即使是4号哲学家,也只能是先申请4号筷子,然后再申请0号筷子
public class PhilosopherEating3 { private static Thread[] threads = new Thread[5]; public static void main(String[] args) { System.out.println("Hello World!"); for(int i = 0 ; i < 5; i ++){ threads[i] = new Thread(new Philosopher(i)); threads[i].start(); } //当前线程组活动线程数 while(Thread.activeCount()>1){ int count = 0; for(int i = 0 ; i < 5; i ++){ if(threads[i].getState().equals(Thread.State.BLOCKED)){ count++; } } if(count == 5){ System.out.println("死锁!!!!!!!!"); for(int i = 0 ; i < 5; i ++ ){ System.out.println(threads[i].getState()); } } try{ Thread.sleep(1000); }catch(InterruptedException ex){ } } } } /* * 哲学家进程 */ class Philosopher implements Runnable { //所有哲学家共用五支筷子 private static Chopstick chopstick = new Chopstick(); //哲学家编号 private int id = 0; public Philosopher(int id){ this.id = id; } public void run(){ while(true){ if(new Random().nextBoolean()){ //取筷子 chopstick.take(id); eat(); //放筷子 chopstick.down(id); }else{ think(); } } } //就餐 private void eat(){ int time = new Random().nextInt(10); try{ System.out.println(id + "就餐"+time+"s"); Thread.sleep(time*100); System.out.println(id + "就餐完成!"); }catch(InterruptedException ex){ System.out.println("ex:eat"); } } //思考 private void think(){ int time = new Random().nextInt(10); try{ System.out.println(id + "思考"+time+"s"); Thread.sleep(time*100); }catch(InterruptedException ex){ System.out.println("ex:think"); } } } /* * 筷子 * 作为资源 */ class Chopstick { //五支筷子资源 private static Semaphore[] used = new Semaphore[5]; public Chopstick(){ for(int i = 0; i < 5; i ++){ used[i] = new Semaphore(1); } } //取筷子 public void take(int id){ //获取锁 try{ if(id < 4){ //先申请号大的筷子 used[id+1].acquire(); //申请号小的筷子 used[id].acquire(); }else{ //id = 4时比较特殊 //先申请号大的筷子 used[id].acquire(); //申请号小的筷子 used[0].acquire(); } }catch(InterruptedException ex){ }finally{ } } //放筷子 public void down(int id){ //先释放小号,再释放大号 if(id < 4){ used[id].release(); used[id+1].release(); }else{ //id = 4时比较特殊 used[0].release(); used[id].release(); } } }
相关文章推荐
- Python图像处理(14):神经网络分类器
- 一致性哈希服务器的数据维护
- hdu 5277 YJC counts stars
- ROS学习手记 - 2 Build Package 生成包
- 突然回到这里,瞅瞅还有几个鬼?
- 面试题34:丑数
- 面向接口编程(简单工厂模式)和单列设计模式
- C# 使用TraceSource记录程序日志(转载)
- [华为机试练习题]57.对象管理器
- 优化
- OSGI学习总结
- Xilinx_fpga 从串配置模式
- JVM基本原理
- 我的 Fedora 20 + django + nginx + uwsgi 配置
- 使用 Google V8 引擎开发可定制的应用程序
- Angular JS ng-app使用的注意事项
- Emmet:HTML/CSS代码快速编写器
- web页面中参数的传递方法
- require.js 应用实例
- redis 在windows上运行