哲学家就餐问题在Java多线程中是一个死锁的典型案例;
问题描述:有一群哲学家,每个哲学家身边都有一支筷子(也就是说哲学家的人数和筷子的人数是相等的;)哲学家有两种状态:吃饭或者思考;我们现在就来具体实现一下:
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
class Chopsticks{
private boolean taken = false;
public synchronized void take() throws InterruptedException{
while(taken){
wait();
taken = true;
}
}
public synchronized void drop(){
taken = false;
notifyAll();
}
}
class Philosopher implements Runnable{
private Chopsticks left;
private Chopsticks right;
private final int id;
private final int ponderFactor;
private Random rand = new Random(100);
public void pause() throws InterruptedException{
if(ponderFactor == 0)
return;
TimeUnit.SECONDS.sleep(rand.nextInt(3));
}
public Philosopher(Chopsticks left, Chopsticks right, int ident, int ponder){
this.left = left;
this.right = right;
id = ident;
ponderFactor = ponder;
}
public void grabbingChopstick() throws InterruptedException{
//System.out.println(this + " " + "在抢右筷子");
right.take();
//System.out.println(this + " " + "在抢左筷子");
left.take();
}
public void thinking() throws InterruptedException{
System.out.println(this + " " + "在思考");
pause();
}
public void eating() throws InterruptedException{
System.out.println(this + " " + "在吃饭");
pause();
right.drop();
left.drop();
}
@Override
public void run() {
try {
while(!Thread.interrupted()){
thinking();
grabbingChopstick();
eating();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String toString(){
return "哲学家-" + id;
}
}
public class TestDemo {
public static void main(String[] args) throws Exception {
Scanner scan = new Scanner(System.in);
int ponder = scan.nextInt();
int size = ponder;
ExecutorService pool = Executors.newCachedThreadPool();
Chopsticks[] sticks = new Chopsticks[size];
for(int i = 0; i < size; i++){
sticks[i] = new Chopsticks();
}
for(int j = 0; j < size; j++){
if(j < size - 1){
pool.execute(new Philosopher(sticks[j],
sticks[(j + 1) % size], j + 1, ponder));
}else{
pool.execute(new Philosopher(sticks[0], sticks[j], j + 1, ponder));
}
}
}
}
上述代码是优化了死锁问题的程序,但是如果我们把程序修改成一下这样,就很容易发生死锁(当出现每一个哲学家都拿到了一支筷子的时候,就会出现死锁现象):
for(int j = 0; j < size; j++){
if(j < size){
pool.execute(new Philosopher(sticks[j],
sticks[(j + 1) % size], j + 1, ponder));
}
}
哲学家问题就跟大家分享到这里,欢迎各位大佬批评指正!