餐饮哲学家问题是计算机科学中的经典问题之一。我打算使用Java线程来实现它。我尝试使用Java5附带的锁定框架,并使用tryLock()方法来避免死锁。我的实现相当简单。我实现了runnable接口来表示哲学家,并使用executor服务来运行所有这些runnable。
作为锁,我使用了ReentrantLock。我知道这里已经讨论了几个实现,但我想了解一下我的实现。
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
public class Philosopher implements Runnable {
private String name;
private final Lock leftFork;
private final Lock rightFork;
public Philosopher(String name, Lock leftFork, Lock rightFork) {
this.name = name;
this.leftFork = leftFork;
this.rightFork = rightFork;
}
public void think() {
log("thinking");
}
public void eat() {
//assume, eating requires some time.
//let's put a random number
try {
log("eating");
int eatingTime = getRandomEatingTime();
TimeUnit.NANOSECONDS.sleep(eatingTime);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
@Override
public void run() {
while (true) {
keepThinkingAndEating();
}
}
private void keepThinkingAndEating() {
think();
if (leftFork.tryLock()) {
try {
log("grabbed left fork");
if (rightFork.tryLock()) {
try {
log("grabbed right fork");
eat();
} finally {
log("put down right fork");
rightFork.unlock();
}
}
} finally {
log("put down left fork");
leftFork.unlock();
}
}
}
private void log(String msg) {
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_TIME;
String time = formatter.format(LocalDateTime.now());
String thread = Thread.currentThread().getName();
System.out.printf("%12s %s %s: %s%n", time, thread, name, msg);
System.out.flush();
}
private int getRandomEatingTime() {
Random random = new Random();
return random.nextInt(500) + 50;
}
}以及运行此代码的主要方法:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class PhilosopherMain {
public static void main(String[] args) {
Lock[] forks = new Lock[5];
for (int i = 0; i < forks.length; i++) {
forks[i] = new ReentrantLock();
}
Philosopher[] philosophers = new Philosopher[5];
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < philosophers.length; i++) {
Lock leftFork = forks[i];
Lock rightFork = forks[(i + 1) % forks.length];
philosophers[i] = new Philosopher("Philosopher " + (i + 1), leftFork, rightFork);
executorService.execute(philosophers[i]);
}
executorService.shutdown();
}
}发布于 2017-11-24 09:09:06
您的实现是极简式的,但它做的是它所做的,并且它做得很好。
您的代码主要由三个元素组成:
1和2并不那么有趣,因为它们可能因实现而略有不同。一般来说,您没有达到一个代码质量来解决任何模块化问题。
第三部分是我想说的。你选择了餐饮哲学家的利己主义变体。如果其他哲学家继续在不利的时刻采取分叉,哲学家可能会面临饥饿。
另一个变体是合作的。你得再介绍一件艺术品才行。哲学家可以直接给他们的邻居,如果他们登记使用叉子,而叉子本身目前是无效的。这使哲学家不能立即松开叉子并再次询问,因此其他哲学家没有机会在此过程中自我介绍。
https://codereview.stackexchange.com/questions/181188
复制相似问题