Multithreading - Dining Philosophers Problem in Java
Tags: thread, concurrency, multithread, webdev
Published: 2024-03-14 15:05:42

## Introduction
The Dining Philosophers Problem illustrates concurrency challenges, where philosophers seated at a table must pick up chopsticks to eat, leading to potential deadlock.

## Solution

- **_Chopstick Class:_** Implements locking mechanisms for chopstick pickup and put down.

```java
public class Chopstick {
    private final Lock lock = new ReentrantLock();
    private final Logger logger = LoggerFactory.getLogger(Chopstick.class);
    public boolean pickUp() {
        try {
            return lock.tryLock(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            return false;
        }
    }
    public void pickDown() {
        lock.unlock();
    }
}
```

- **_Philosopher Class:_** Represents each philosopher, managing chopstick pickup and eating.

```java
public class Philosopher implements Runnable {
    private final Logger logger = LoggerFactory.getLogger(Philosopher.class);
    private int id;
    private Chopstick leftStick;
    private Chopstick rightStick;

    public Philosopher(int id, Chopstick leftStick, Chopstick rightStick) {
        this.id = id;
        this.leftStick = leftStick;
        this.rightStick = rightStick;
    }

    @Override
    public void run() {
        while (true) {
            try {
                logger.info("Philosopher " + id + " is thinking.");
                if (leftStick.pickUp()) {
                    logger.info("Philosopher " + id + " picked up left stick.");
                    if (rightStick.pickUp()) {
                        logger.info("Philosopher " + id + " picked up right stick.");
                        logger.info("Philosopher " + id + " is eating.");
                        rightStick.pickDown();
                        logger.info("Philosopher " + id + " pick down right stick.");
                    }
                    leftStick.pickDown();
                    logger.info("Philosopher " + id + " pick down left stick.");
                }
            } catch (Exception e) {
                Thread.currentThread().interrupt();
                return;
            }
        }
    }
}
```
- **_Main Class (Driver):_** Sets up philosophers and chopsticks, employing thread pooling for execution.

```java
public class Driver {
    private static final Logger logger = LoggerFactory.getLogger(Driver.class);
    private static final Philosopher[] philosophers = new Philosopher[5];
    private static final Chopstick[] chopsticks = new Chopstick[5];

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(5, runnable -> {
            Thread thread = Executors.defaultThreadFactory().newThread(runnable);
            thread.setPriority(Thread.MAX_PRIORITY);
            return thread;
        });
        for (int i = 0; i < chopsticks.length; i++) {
            chopsticks[i] = new Chopstick();
        }
        for (int i = 0; i < philosophers.length; i++) {
            philosophers[i] = new Philosopher(i + 1, chopsticks[i], chopsticks[(i + 1) % 5]);
            executorService.execute(philosophers[i]);
        }
    }
}
```

## Conclusion
By synchronizing chopstick access and implementing a thoughtful eating protocol, we ensure the philosophers can dine peacefully without encountering deadlock or contention issues.