多线程系列之哲学家进餐

晚上学习了多线程的知识,总结了哲学家进餐问题,分享给大家.

 

  1 package thread;

  2 

  3 import java.util.Random;

  4 // 哲学家进餐问题

  5 

  6 /* 同时满足以下四个条件时,就会发生死锁

  7  * 1. 互斥条件:线程使用的资源中至少有一个是不能共享的.这里,一根筷子一次就只能

  8  *    被一个哲学家使用.

  9  * 2. 至少有一个线程持有一个资源,并且它在等待获取一个当前被别的线程持有的资源.也就是

 10  *    说,要放生死锁,哲学家必须拿着一根筷子并且等待另一根.

 11  * 3. 资源不能被进程(线程)抢占.所有的进程必须把资源释放作为普通条件.哲学家很有礼貌,

 12  *    不会从其他哲学家那里抢筷子.

 13  * 4. 必须有循环等待,这时,一个进程等待其他进程持有的资源,后者又在等待另外一个进程持有的

 14  *    资源,这样一直下去,直到有一个进程在等待第一个进程(线程)持有的资源,使得大家都被锁住.

 15  *    在这里,以为每个哲学家都试图先得到左边的筷子,然后得到右边的筷子,所以发生了循环等待.

 16  *    在下面的例子中,针对最后一个哲学家,通过交换构造器中的初始化顺序,打破了死锁条件,使得

 17  *    最后一个哲学家先拿右边的筷子,再拿左边的筷子.

 18  */

 19 class Chopstick {

 20     private static int counter = 0;

 21     private int number = counter++;

 22 

 23     public String toString() {

 24         return "Chopstick " + number;

 25     }

 26 }

 27 

 28 class Philosopher extends Thread {

 29     private static Random rand = new Random();

 30     private static int counter = 0;

 31     private int number = counter++;

 32     private Chopstick leftChopstick;

 33     private Chopstick rightChopstick;

 34     static int ponder = 0; // Package access

 35 

 36     public Philosopher(Chopstick left, Chopstick right) {

 37         leftChopstick = left;

 38         rightChopstick = right;

 39         start();

 40     }

 41 

 42     public void think() {

 43         System.out.println(this + " thinking");

 44         if (ponder > 0)

 45             try {

 46                 sleep(rand.nextInt(ponder));

 47             } catch (InterruptedException e) {

 48                 throw new RuntimeException(e);

 49             }

 50     }

 51 

 52     public void eat() {

 53         synchronized (leftChopstick) {

 54             System.out.println(this + " has " + this.leftChopstick

 55                     + " Waiting for " + this.rightChopstick);

 56             synchronized (rightChopstick) {

 57                 System.out.println(this + " eating");

 58             }

 59         }

 60     }

 61 

 62     public String toString() {

 63         return "Philosopher " + number;

 64     }

 65 

 66     public void run() {

 67         while (true) {

 68             think();

 69             eat();

 70         }

 71     }

 72 }

 73 

 74 public class DiningPhilosophers {

 75     public static void main(String[] args) {

 76         args = new String[4];

 77         args[0] = "5"; // 哲学家数

 78         args[1] = "0"; // 思考时间

 79         args[2] = "deadlock"; // 指定发生死锁

 80 

 81         Philosopher[] philosopher = new Philosopher[Integer.parseInt(args[0])];

 82         Philosopher.ponder = Integer.parseInt(args[1]);

 83 

 84         // first指向left指向的地址,left重新指向其他地方,first不跟随改变

 85         Chopstick left = new Chopstick(), right = new Chopstick(), first = left;

 86         int i = 0;

 87         while (i < philosopher.length - 1) {

 88             philosopher[i++] = new Philosopher(left, right);

 89             left = right;

 90             right = new Chopstick();

 91         }

 92 

 93         if (args[2].equals("deadlock"))

 94             philosopher[i] = new Philosopher(left, first);

 95         else

 96             // 交换最后一个哲学家拿筷子的顺序,打破死锁

 97             philosopher[i] = new Philosopher(first, left);

 98 

 99     }

100 } // /:~

 

 

你可能感兴趣的:(多线程)