Javaマルチスレッド-哲学者の食事問題

2286 ワード

哲学者の食事問題
一つの円卓の前に5人の哲学者が座っていて、二人の間に箸があり、テーブルの中央にうどんがあります.哲学者は、お腹が空いたときに左右の箸を持って食事をするには、箸を2つ持ってから食事をしなければならないと考えている.上記の問題でデッドロックが発生する場合、5人の哲学者が右手の箸を持ち、左手の箸を持つ準備をしている間にデッドロックが発生する.
解決策:
1、ウェイターを追加して、ウェイターの同意を得てから箸を取ることができて、ウェイターはデッドロックの発生を避ける責任を負います.
2、すべての哲学者は自分の左右の手の箸が使えることを確定しなければならない時、同時に2本の箸を持って食事をして、食べ終わった後に同時に2本の箸を置くことができます.3、哲学者一人一人が箸を取るときは番号の小さいものを取らなければならないと規定されています.そうすれば、最後の箸を取らなかった哲学者は番号の大きい箸しか残っていません.取ってはいけません.残りの箸は他の哲学者に使われ、デッドロックを避けることができます.このような状況では資源をうまく利用できない. 
きほんインプリメンテーションコード
//  
public class Test {

	public static void main(String[] args) {
		Fork fork = new Fork();
		new Philosopher("0", fork).start();
		new Philosopher("1", fork).start();
		new Philosopher("2", fork).start();
		new Philosopher("3", fork).start();
		new Philosopher("4", fork).start();
	}
}

class Philosopher extends Thread {
	private String name;
	private Fork fork;

	public Philosopher(String name, Fork fork) {
		super(name);
		this.name = name;
		this.fork = fork;
	}

	public void run() {
		while (true) {
			thinking();
			fork.takeFork();
			eating();
			fork.putFork();
		}
	}

	public void eating() {
		System.out.println("I am Eating:" + name);
		try {
			sleep(1000);//     ,        
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public void thinking() {
		System.out.println("I am Thinking:" + name);
		try {
			sleep(1000);//     
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

class Fork {
	/* 5   ,        */
	private boolean[] used = { false, false, false, false, false, false };

	/*                ,       ,             */
	public synchronized void takeFork() {
		String name = Thread.currentThread().getName();
		System.out.println("try take : " + name);
		int i = Integer.parseInt(name);
		while (used[i] || used[(i + 1) % 5]) {
			try {
				wait();//             ,  
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		used[i] = true;
		used[(i + 1) % 5] = true;
	}

	/*              */
	public synchronized void putFork() {
		String name = Thread.currentThread().getName();
		int i = Integer.parseInt(name);

		used[i] = false;
		used[(i + 1) % 5] = false;
		notifyAll();//       
	}
}