public class Philosophers implements Runnable { private Semaphore leftFork; private Semaphore rightknife; private int id; public Philosophers(int id, Semaphore leftFork, Semaphore rightknife) { this.id = id; this.leftFork = leftFork; this.rightknife = rightknife; } public void run() { try { //思考 System.out.println("哲学家" + id + "正在思考"); Thread.sleep((long) (Math.random() * 10000)); //进餐 System.out.println("哲学家" + id + "饿了,开始进餐"); leftFork.acquire(); System.out.println("哲学家" + id + "拿起左边的叉子"); rightknife.acquire(); System.out.println("哲学家" + id + "拿起右边的刀子"); Thread.sleep((long) (Math.random() * 10000)); System.out.println("哲学家" + id + "进餐完毕,放下叉子"); //释放叉子 rightknife.release(); System.out.println("哲学家" + id + "放下右边的刀子"); leftFork.release(); System.out.println("哲学家" + id + "放下左边的叉子"); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { int N = 5; //哲学家数量 Semaphore[] forks = new Semaphore[N]; for (int i = 0; i < N; i++) { forks[i] = new Semaphore(1); } for (int i = 0; i < N; i++) { new Thread(new Philosophers(i, forks[i], forks[(i + 1) % N])).start(); } } }
时间: 2024-02-14 08:22:54 浏览: 11
这段代码实现了哲学家进餐问题的解决方案。在该问题中,有五位哲学家围绕着一张圆桌坐着,每位哲学家需要同时使用他们左右两边的叉子和刀子才能吃饭。由于叉子和刀子只有一份,因此需要使用信号量来进行同步控制。在这段代码中,Semaphore类被用来控制叉子和刀子的访问,每个Semaphore对象的初始值都为1,表示只有一个哲学家可以拿起叉子或刀子。当哲学家需要进餐时,他会先尝试获取左边的叉子和右边的刀子,如果成功获取到,则可以进餐,否则他必须等待其他哲学家放下叉子和刀子。当哲学家进餐结束后,他必须放下左右两边的叉子和刀子,以便其他哲学家可以使用它们。
相关问题
public class Philosophers implements Runnable { private Semaphore leftFork; private Semaphore rightknife; private int id; public Philosophers(int id, Semaphore leftFork, Semaphore rightknife) { this.id = id; this.leftFork = leftFork; this.rightknife = rightknife; } public void run() { try { //思考 System.out.println("哲学家" + id + "正在思考"); Thread.sleep((long) (Math.random() * 10000)); //进餐 System.out.println("哲学家" + id + "饿了,开始进餐"); leftFork.acquire(); System.out.println("哲学家" + id + "拿起左边的叉子"); rightknife.acquire(); System.out.println("哲学家" + id + "拿起右边的刀子"); Thread.sleep((long) (Math.random() * 10000)); System.out.println("哲学家" + id + "进餐完毕,放下叉子"); //释放叉子 rightknife.release(); System.out.println("哲学家" + id + "放下右边的刀子"); leftFork.release(); System.out.println("哲学家" + id + "放下左边的叉子"); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { int N = 5; //哲学家数量 Semaphore[] forks = new Semaphore[N]; for (int i = 0; i < N; i++) { forks[i] = new Semaphore(1); } for (int i = 0; i < N; i++) { new Thread(new Philosophers(i, forks[i], forks[(i + 1) % N])).start(); } } }优化上述代码避免发生死锁并为各行代码添加注释
为了避免死锁,需要对程序中的资源竞争进行优化。下面是对代码进行的修改:
```
public class Philosophers implements Runnable {
private Semaphore leftFork;
private Semaphore rightFork; // 修改成叉子的信号量
private int id;
public Philosophers(int id, Semaphore leftFork, Semaphore rightFork) {
this.id = id;
this.leftFork = leftFork;
this.rightFork = rightFork;
}
public void run() {
try {
//思考
System.out.println("哲学家" + id + "正在思考");
Thread.sleep((long) (Math.random() * 10000));
//进餐
System.out.println("哲学家" + id + "饿了,开始进餐");
// 判断左右叉子,只有当两个叉子都可用时才能取到叉子
if (id % 2 == 0) {
leftFork.acquire();
System.out.println("哲学家" + id + "拿起左边的叉子");
rightFork.acquire();
System.out.println("哲学家" + id + "拿起右边的叉子");
} else {
rightFork.acquire();
System.out.println("哲学家" + id + "拿起右边的叉子");
leftFork.acquire();
System.out.println("哲学家" + id + "拿起左边的叉子");
}
Thread.sleep((long) (Math.random() * 10000));
System.out.println("哲学家" + id + "进餐完毕,放下叉子");
//释放叉子
rightFork.release();
System.out.println("哲学家" + id + "放下右边的叉子");
leftFork.release();
System.out.println("哲学家" + id + "放下左边的叉子");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
int N = 5; //哲学家数量
Semaphore[] forks = new Semaphore[N];
for (int i = 0; i < N; i++) {
forks[i] = new Semaphore(1);
}
for (int i = 0; i < N; i++) {
new Thread(new Philosophers(i, forks[i], forks[(i + 1) % N])).start();
}
}
}
```
注释如下:
1. 将 rightknife 修改为 rightFork,以更好地反映代码含义。
2. 在进餐前,对哲学家编号进行判断,偶数编号的哲学家先取左边的叉子,奇数编号的哲学家先取右边的叉子。
3. 注释相关代码,方便理解和调试。
用java实现实现哲学家进餐问题
哲学家进餐问题是一个经典的同步问题,主要涉及到多个进程(哲学家)之间的资源竞争问题。在这个问题中,每个哲学家都需要交替地进行思考和进餐,但是他们共享一些资源,如餐具等,因此需要协调它们的行为以避免死锁和饥饿等问题。
下面是使用 Java 实现哲学家进餐问题的示例代码:
```java
import java.util.concurrent.Semaphore;
public class Philosopher implements Runnable {
private final int id;
private final Semaphore leftFork;
private final Semaphore rightFork;
public Philosopher(int id, Semaphore leftFork, Semaphore rightFork) {
this.id = id;
this.leftFork = leftFork;
this.rightFork = rightFork;
}
@Override
public void run() {
try {
while (true) {
think();
leftFork.acquire();
rightFork.acquire();
eat();
rightFork.release();
leftFork.release();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
private void think() throws InterruptedException {
System.out.println("Philosopher " + id + " is thinking");
Thread.sleep((long) (Math.random() * 5000));
}
private void eat() throws InterruptedException {
System.out.println("Philosopher " + id + " is eating");
Thread.sleep((long) (Math.random() * 5000));
}
}
public class DiningPhilosophers {
private static final int NUM_PHILOSOPHERS = 5;
public static void main(String[] args) {
Semaphore[] forks = new Semaphore[NUM_PHILOSOPHERS];
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
forks[i] = new Semaphore(1);
}
Philosopher[] philosophers = new Philosopher[NUM_PHILOSOPHERS];
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
philosophers[i] = new Philosopher(i, forks[i], forks[(i + 1) % NUM_PHILOSOPHERS]);
new Thread(philosophers[i]).start();
}
}
}
```
在这个示例代码中,我们创建了一个 `Philosopher` 类和一个 `DiningPhilosophers` 类,其中 `Philosopher` 类实现了哲学家的行为,而 `DiningPhilosophers` 类则负责创建和启动哲学家线程。
在 `Philosopher` 类中,我们使用了两个信号量 `leftFork` 和 `rightFork` 表示哲学家左边和右边的餐叉。在 `run` 方法中,哲学家先思考一段时间,然后尝试获取左右餐叉的信号量。如果成功获取了两个餐叉的信号量,哲学家就可以进餐。最后,哲学家释放左右餐叉的信号量,以便其他哲学家可以使用它们。
在 `DiningPhilosophers` 类中,我们首先创建了一个 `Semaphore` 数组 `forks`,其中每个元素都表示一个餐叉。然后,我们创建了五个 `Philosopher` 对象,并将它们的左右餐叉设置为相邻的两个 `Semaphore` 对象。最后,我们创建了五个线程,每个线程都对应一个哲学家,并启动它们。当程序运行时,每个哲学家会交替进行思考和进餐,直到程序被中断或终止。
相关推荐
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)