线程学习五:哲学家就餐问题

问题描述:

设有5个哲学家,共享一张放有5把椅子的桌子,每人分得一把椅子,但是,桌子上共有5只筷子,在每人两边各放一只,哲学家们在肚子饥饿时才试图分两次从两边拿起筷子就餐。
条件:
1)拿到两只筷子时哲学家才开始吃饭。
2)如果筷子已在他人手上,则该哲学家必须等他人吃完之后才能拿到筷子。
3)任一哲学家在自己未拿到两只筷子前却不放下自己手中的筷子。

解题思路:

如果哲学家身边的2把筷子都没人使用,哲学家便可以就餐,否者哲学家只能等待别人就餐完毕。那么就根据哲学家身边的筷子状态做判断,满足条件便就餐,不满足则等待

代码:

 1 public class PhilosopherTest {
 2     public static void main(String args[]) {
 3         Philosopher pl = new philosopher1();
 4         Thread thread1 = new Thread(pl, "1");
 5         Thread thread2 = new Thread(pl, "2");
 6         Thread thread3 = new Thread(pl, "3");
 7         Thread thread4 = new Thread(pl, "4");
 8         Thread thread5 = new Thread(pl, "5");
 9         thread1.start();
10         thread2.start();
11         thread3.start();
12         thread4.start();
13         thread5.start();
14     }
15
16 }
17
18 class Philosopher implements Runnable{
19     private static boolean[] fork = { false, false, false, false, false};
20
21     @Override
22     public void run() {
23         while (true) {
24                 eating();
25                 thinking();
26         }
27     }
28
29     public synchronized void eating() {
30         try{
31             int i = Integer.parseInt(Thread.currentThread().getName());
32             if (fork[i % 5] == false && fork[i - 1] == false){
33             Thread.sleep(500);//模拟吃饭过程
34             System.out.println("当前在吃饭的是" + Thread.currentThread().getName());
35             fork[i % 5] = true;
36             fork[i - 1] = true;
37             }else{
38                 wait();
39             }
40         }catch(Exception e){
41             e.printStackTrace();
42         }
43     }
44
45     public synchronized void thinking() {
46         try{
47             int i = Integer.parseInt(Thread.currentThread().getName());
48             if (fork[i % 5] == true && fork[i - 1] == true) {
49             Thread.sleep(500);//模拟思考过程
50             System.out.println(Thread.currentThread().getName() + "已经吃完饭了");
51             fork[i % 5] = false;
52             fork[i - 1] = false;
53             notifyAll();
54             }
55         }catch(Exception e){
56             e.printStackTrace();
57         }
58
59     }
60 }
时间: 2025-01-08 22:36:28

线程学习五:哲学家就餐问题的相关文章

Thking in Java---从哲学家就餐问题看死锁现象

我们知道一个对象可以有synchronized方法或其他形式的加锁机制来防止别的线程在互斥还没释放的时候就访问这个对象.而且我们知道线程是会变成阻塞状态的(挂起),所以有时候就会发生死锁的情况:某个任务在等待另一个任务,而后者又在等待其它任务,这样一直下去,知道这个链条下的任务又在等待第一个任务释放锁,这样就形成了一个任务之间相互等待的连续循环,没有任务可以继续的情况.死锁的最大问题在于它发生的几率非常小,并不是我们一运行程序它就死锁了,而是会不知道那个时候程序就死锁了并且我们很难重现当时出现死

从哲学家就餐问题彻底认识死锁

第一节  哲学家就餐问题 第二节  什么是死锁 第三节  死锁的定义 第四节  死锁发生的条件 第五节  如何避免死锁 5.1 动态避免,银行家算法(杠杆分配),在资源分配上下文章 5.2 静态避免,从任务代码上避免死锁 第六节  死锁的综合治理 第一节  哲学家就餐问题 假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考.吃东西的时候,他们就停止思考,思考的时候也停止吃东西.餐桌中间有一大碗意大利面,每两个哲学家之间有一双筷子.因为用一只筷子很难吃到意大利面,所以假设哲学

IPC问题-哲学家就餐

如上图,有五位哲学家,盘中的食物只有左右两个叉子都拿起才能吃.哲学家在桌上只有思考(等待)和吃面(执行).看起来最多是只有2个人能同时吃. 版本一:这个思路的最糟糕的就是都拿起左边叉子,那样都没法吃了,直接死锁. 版本二:改进版本一,如果拿起左边叉子,先看右边是否能用,不可用的话放下左边叉子等待一段时间再运行.这个思路的问题就是,会产生某个时刻每个人都拿起左叉子,又放下,又拿起,虽然没有死锁,但是没有人在吃面,消耗了性能但是任务没有进展,造成饥饿. 版本三:改进版本二,每次等待右边是否能用的每个

Java线程学习整理--3--简单的死锁例子

1.线程死锁的概念: 简单地理解下吧! 我们都知道,线程在执行的过程中是占着CPU的资源的,当多个线程都需要一个被锁住的条件才能结束的时候,死锁就产生了! 还有一个经典的死锁现象: 经典的“哲学家就餐问题”,5个哲学家吃中餐,坐在圆卓子旁.每人有5根筷子(不是5双),每两个人中间放一根,哲学家时而思考,时而进餐. 每个人都需要一双筷子才能吃到东西,吃完后将筷子放回原处继续思考,如果每个人都立刻抓住自己左边的筷子,然后等待右边的筷子空出来,同时又不 放下已经拿到的筷子,这样每个人都无法得到1双筷子

JAVA并发,经典死锁案例-哲学家就餐

转自:http://blog.csdn.net/tayanxunhua/article/details/38691005 死锁经典案例:哲学家就餐. 这个案例会导致死锁. 通过修改<Java编程思想4>一书中的案例,来做实验,代码更易理解,结果也相对容易控制. 附代码: 筷子类: 1 package com.tyxh.ch21.c6; 2 3 public class Chopstick { 4 private boolean taken = false;//判断是此筷子是否被拿起 5 pub

Linux线程学习(二)

一.Linux进程与线程概述 进程与线程 为什么对于大多数合作性任务,多线程比多个独立的进程更优越呢?这是因为,线程共享相同的内存空间.不同的线程可以存取内存中的同一个变量.所以,程序中的所有线程都可以读或写声明过的全局变量.如果曾用fork() 编写过重要代码,就会认识到这个工具的重要性.为什么呢?虽然fork() 允许创建多个进程,但它还会带来以下通信问题:如何让多个进程相互通信,这里每个进程都有各自独立的内存空间.对这个问题没有一个简单的答案.虽然有许多不同种类的本地IPC (进程间通信)

Java线程学习笔记(一)

一.线程的创建方式: 老掉牙的话题了,继承 java.lang.Thread父类或者实现Runnalbe接口,这里就提一句: class Thread implements Runnable Thread也是继承了Runnable接口的,Runnable才是大哥. 重写run(),run()里放的都是具体的业务,包括对线程的具体操作. class Thread1 implements Runnable { int i; Thread1(int i) { this.i = i; } @Overri

Hadoop学习(五)-MapReduce架构原理

概述 hadoop主要是用于应对海量数据的存储和计算的,前面hdfs文件系统,则重点是用于海量数据的存储.那么有了这么多数据,我们又该怎么在这些数据里面来提取我们需要的信息呢?这个时候hadoop中出现了一个非常重要的成员MapReduce.MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算.注意这个并行运算,它不再是我们传统意义上的串行计算,它可以在不同的进程中进行并行的运算.概念"Map(映射)"和"Reduce(归约)",是它们的主要思

Java线程学习经典例子-读写者演示

Java线程学习最经典的例子-读写者,主要用到Thread相关知识如下: -         线程的start与run -         线程的休眠(sleep) -         数据对象加锁(synchronized) -         数据对象的等待与释放(wait and notify) 程序实现: -ObjectData数据类对象,通过synchronized关键字实现加锁,在线程读写者中使用. -ConsumerThread消费者线程,读取数据对象中count值之后,通知生产者