Java.

Java. Проблема пяти философов

Цель задания — познакомиться с одной из классических проблем теории параллелизма — проблемой пяти философов (автор Э. В. Дейкстра).

Java. Проблема пяти философов

  • Каждый философ в основном занимается мышлением
  • Время от времени ему нужно поесть
  • Для еды ему нужны обе вилки справа и слева от него
  • Пища занимает конечное (но неопределенное заранее) количество времени, после чего философ откладывает вилки и возвращается к размышлениям
  • Цикл повторяется с самого начала
package com.company;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Main {

public static void main(String[] args) {

List<Fork> forks = new ArrayList<>();
List<Philosopher> philosophers = new ArrayList<>();

for (int i = 0; i < 5; i++) {
forks.add(new Fork(i));
}

for (int i = 0; i < 5; i++) {
philosophers.add(new Philosopher(i, forks.get(i), forks.get((i+1) % 5)));
}

for (int i = 0; i < 5; i++) {
Thread thread = new Thread(philosophers.get(i));
thread.start();
}
}
}

class Fork {
public int id;

public Fork(int id) {
this.id = id;
}

public int getId() {
return this.id;
}

public String eat() {
return "Fork";
}
}

class Philosopher implements Runnable {
public int id;
public Fork forkLeft;
public Fork forkRight;

public Philosopher(int id, Fork forkLeft, Fork forkRight) {
this.id = id;
this.forkRight = forkRight;
this.forkLeft = forkLeft;
}

public int getId() {
return this.id;
}

@Override
public void run() {
while (true) {
this.thinkAboutLife();
this.eatDinner();
}
}

private void thinkAboutLife() {
System.out.printf("Philosopher think: %d\n", this.id);
}

private void eatDinner() {
System.out.printf("Philosopher dinner: %d\n", this.getId());
synchronized (forkLeft) {
System.out.printf("P: %d Fork left: %d\n", this.id, forkLeft.getId());
synchronized (forkRight) {
System.out.printf("P: %d Fork right: %d\n", this.id, forkRight.getId());
}
}
}
}
  • a. Реализовать тривиальное решение. Обратите внимание на проблему блокировки.
  • b. Проведите измерения для каждого решения и определите, что влияет на производительность каждого решения.
  • c. Используйте семафоры и блокировки из JCU для решения проблемы.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
    static final int PHILOSOFERS = 5;

    public static void main(String[] args) {

        List<Fork> forks = new ArrayList<>();
        List<Philosopher> philosophers = new ArrayList<>();

        for (int i = 0; i < PHILOSOFERS; i++) {
            forks.add(new Fork(i));
        }

        for (int i = 0; i < PHILOSOFERS; i++) {
            philosophers.add(new Philosopher(i, forks.get(i), forks.get((i+1) % 5)));
        }

        for (int i = 0; i < PHILOSOFERS; i++) {
            Thread thread = new Thread(philosophers.get(i));
            thread.start();
        }

    }
}

class Fork {
    public int id;
    Semaphore semaphore;

    public Fork(int id) {
        this.id = id;
        this.semaphore = new Semaphore(1);
    }

    public void forkUp() {
        try {
            semaphore.acquire();
            System.out.printf("Fork up: %d\n", this.id);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void forkDown() {
        System.out.printf("Fork down: %d\n", this.id);
        semaphore.release();
    }
}

class Philosopher implements Runnable {
    public int id;
    public Fork forkLeft;
    public Fork forkRight;

    public Philosopher(int id, Fork forkLeft, Fork forkRight) {
        this.id = id;
        this.forkRight = forkRight;
        this.forkLeft = forkLeft;
    }

    public int getId() {
        return this.id;
    }

    public void thinkAboutLife() {
        System.out.printf("Philosopher start think: %d\n", this.id);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.printf("Philosopher end think: %d\n", this.id);
    }

    public void eat() {
        System.out.printf("Philosopher start eat: %d\n", this.id);
        forkRight.forkUp();
        forkLeft.forkUp();
        eatSpaghetti();
        forkRight.forkDown();
        forkLeft.forkDown();
        System.out.printf("Philosopher end eat: %d\n", this.id);
    }

    public void eatSpaghetti() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true) {
            thinkAboutLife();
            eat();
        }
    }
}</span>
Warface Statistics.png Assistant for Apex Legends.png Assistant PUBG.png

от STILET

Добавить комментарий