Java实验三 多线程
哲学家进餐问题:
5个哲学家共用一张圆桌,分别坐在周围的5张椅子上,
在圆桌上有5个碗和5只筷子(注意是5只筷子,不是5双),
碗和筷子交替排列。他们的生活方式是交替地进行思考(thinking)和进餐(eating)。
平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的两只筷子,规定他必须先取左边的筷子,再取右边的筷子。
只有在他拿到两只筷子时才能进餐。
进餐完毕,放下筷子继续进行思考。
假如5位哲学家同时饥饿,各自拿起左边的筷子时,再去拿各自右边的筷子,因为无筷子可拿而陷入无期限等待(死锁)。
一种解决的办法是:至多只允许有4位哲学家同时去拿左边的筷子,最终能保证至少有一位哲学家能够拿到两只筷子,从而进餐。
进餐完毕释放他用过的两只筷子,从而使更多的哲学家能够进餐。使用Java的多线程同步技术,实现上述解决方案。
思路都在代码里了
代码:
package phi;
import java.util.concurrent.locks.Lock;
class phiPerson implements Runnable{ //实现Runnable接口
//全部使用static关键字 静态成员属于整个类,当系统第一次使用该类时,就会为其分配内存空间直到该类被卸载才会进行资源回收
//为什么用static修饰 因为多线程多个哲学家需要共享筷子这个对象
static Object[] chops;//static关键字修饰的变量 该类所有的对象共享同一个成员
// static Object[] bowls = new Object()[5]; //碗就不用了吧
static int curTime = 0; //同时拿左手边筷子的人数 也是全局变量
private int pos; //当前哲学家的编号 私有变量
static Object lock = new Object();//static全局变量 同步代码块的锁
public phiPerson(int position,Object[] chops) { //构造函数
// TODO Auto-generated constructor stub
this.chops = chops;
this.pos = position;
}
@Override
public void run() { //重写run方法
// TODO Auto-generated method stub
while(true) {
int right = (pos-1+5)%5; //我右边筷子在数组中的下标
int left = (pos)%5;//左边筷子在数组中的下标
if(curTime < 4) { //最多允许4个人同时拿左手边的筷子
curTime++;//同时拿左手边筷子的人的数量+1
synchronized (lock) { //加锁后 变成同步代码 同时拿左手边的筷子需要小于4人
synchronized (chops[left]) { //锁 左手边的筷子 就是等待左边的人用我左手边的筷子吃完了后我再拿来吃。。
System.out.println(curTime);
System.out.println("第"+(pos+1)+"个哲学家拿了左手边的筷子");
synchronized(chops[right]) {//右手边的筷子 锁 就是等待右手边的筷子没人拿了我再拿
System.out.println("第"+(pos+1)+"个哲学家拿了右手边的筷子");
System.out.println("第"+(pos+1)+"个哲学家正在eating");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("第"+(pos+1)+"个哲学家吃完了,把筷子放回了原处,开始thinking");
curTime--;//同时拿左手边筷子的人的数量-1
}
}
}
}
}
}
}
public class phiEat {
public static void main(String[] args) {
// TODO Auto-generated method stub
Object [] chObject = new Object[5];
for(int i=0;i<5;i++) chObject[i] = i; //object必须要初始化一下呀
//5个哲学家
phiPerson firThread = new phiPerson(0,chObject);
phiPerson secThread = new phiPerson(1,chObject);
phiPerson thirThread = new phiPerson(2,chObject);
phiPerson fourThread = new phiPerson(3,chObject);
phiPerson fifThread = new phiPerson(4,chObject);
//开吃了
new Thread(firThread).start();
new Thread(secThread).start();
new Thread(thirThread).start();
new Thread(fourThread).start();
new Thread(fifThread).start();
}
}