Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ЛАБЫ / индивидуалка отчёт

.docx
Скачиваний:
3
Добавлен:
13.06.2024
Размер:
120.08 Кб
Скачать

еФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ

УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ

«САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ТЕЛЕКОММУНИКАЦИЙ ИМ. ПРОФ. М.А. БОНЧ-БРУЕВИЧА»

(СПбГУТ)

_____________________________________________________________________

Факультет Информационных систем и технологий

Кафедра Безопасности информационных систем

Дисциплина «Кроссплатформенное программирование»

ОТЧЕТ

по индивидуальному заданию

Тема: Обедающие философы

Выполнил

Студент 2 курса, гр. ИСТ-222

__________ Шумов В.В.

Принял

Зав. кафедрой БИС

____________ Бородянский Ю.М.

Введение: Задача об обедающих философах является классической проблемой синхронизации, иллюстрирующей необходимость управления ресурсами в многозадачных системах. В данной реализации используется графический интерфейс (GUI), чтобы визуализировать состояния философов и их взаимодействие с вилками

Теоретическая часть: Пять философов сидят вокруг круглого стола, перед каждым из них стоит тарелка спагетти. Между каждой парой ближайших философов лежит по одной вилке. Каждый философ может либо размышлять, либо есть. Для того чтобы есть, философ должен взять обе вилки (левую и правую). Философы должны чередовать прием пищи и размышления таким образом, чтобы ни один из них не голодал.

Решение с использованием официанта: В данной реализации используется официант, который управляет доступом к вилкам. Официант предотвращает взаимную блокировку, разрешая философам брать вилки только тогда, когда это безопасно.

Структура проекта:

1. UIUpdater.java: Интерфейс, определяющий методы для обновления состояния философов и вилок в графическом интерфейсе.

2. Waiter.java: Класс, управляющий доступом к вилкам, чтобы предотвратить взаимную блокировку. Синхронизированные методы requestPermission и releaseForks обеспечивают корректное управление ресурсами.

3. Fork.java: Класс, представляющий вилку. Включает методы для взятия (`pickUp`) и освобождения (`putDown`) вилки с использованием синхронизации для предотвращения конфликтов.

4. Philosopher.java: Класс, определяющий поведение философов. Философы чередуют размышления, прием пищи и сон. При приеме пищи философы запрашивают разрешение у официанта, берут вилки, едят, а затем освобождают вилки и уведомляют официанта.

5. DiningPhilosophersGUI.java: Класс, создающий графический интерфейс. Включает методы для загрузки и отображения изображений, а также обновления состояния философов и вилок. В main методе инициализируются философы и официант, и запускается процесс моделирования.

Ход работы:

(начальное положение философов)

(один ест, остальные отдыхают/думают)

(один ест, остальные отдыхают/думают)

Вывод: Реализация задачи об обедающих философах с графическим интерфейсом демонстрирует применение многопоточности и синхронизации в Java для решения проблем управления ресурсами. Визуализация позволяет наглядно наблюдать за состоянием системы и обеспечивает более интуитивное понимание процесса.

Приложение

UIUpdater.java

package diningphilosophers; // Интерфейс для обновления состояния философов и вилок в графическом интерфейсе public interface UIUpdater { // Метод для обновления состояния философа (думает, ест, спит) void updatePhilosopherState(int id, String state); // Метод для обновления состояния вилки (левая или правая, взята или нет) void updateForkState(int philosopherId, String forkPosition, boolean isPickedUp); }

Waiter.java

package diningphilosophers; // Класс Waiter управляет доступом к вилкам для предотвращения взаимной блокировки public class Waiter { private final int NUM_FORKS; // Количество вилок private int availableForks; // Количество доступных вилок public Waiter(int numForks) { this.NUM_FORKS = numForks; this.availableForks = numForks; } // Метод для запроса разрешения на взятие вилок public synchronized boolean requestPermission() { if (availableForks > 1) { availableForks -= 2; return true; } return false; } // Метод для освобождения вилок public synchronized void releaseForks() { availableForks += 2; } }

Fork.java

package diningphilosophers; // Класс Fork представляет вилку, которую могут брать и возвращать философы public class Fork { private boolean isPickedUp = false; // Состояние вилки (взята или нет) // Метод для взятия вилки public synchronized void pickUp() throws InterruptedException { while (isPickedUp) { wait(); } isPickedUp = true; } // Метод для возвращения вилки public synchronized void putDown() { isPickedUp = false; notify(); } }

Philoshopher.java

package diningphilosophers; // Класс Philosopher представляет философа, который может думать, есть и спать public class Philosopher extends Thread { private static final int SLEEP_TIME = 5000; // Время сна (5 секунд) private final int id; // Идентификатор философа private final Fork leftFork; // Левая вилка private final Fork rightFork; // Правая вилка private final Waiter waiter; // Официант, управляющий доступом к вилкам private final UIUpdater uiUpdater; // Обновление состояния в графическом интерфейсе public Philosopher(int id, Fork leftFork, Fork rightFork, Waiter waiter, UIUpdater uiUpdater) { this.id = id; this.leftFork = leftFork; this.rightFork = rightFork; this.waiter = waiter; this.uiUpdater = uiUpdater; } // Метод для размышления философа private void think() throws InterruptedException { uiUpdater.updatePhilosopherState(id, "Thinking"); Thread.sleep(SLEEP_TIME); } // Метод для еды философа private void eat() throws InterruptedException { uiUpdater.updatePhilosopherState(id, "Eating"); Thread.sleep(SLEEP_TIME); } // Метод для сна философа private void sleep() throws InterruptedException { uiUpdater.updatePhilosopherState(id, "Sleeping"); Thread.sleep(SLEEP_TIME); } @Override public void run() { try { while (true) { think(); // Философ размышляет if (waiter.requestPermission()) { // Запрашивает разрешение у официанта leftFork.pickUp(); // Берет левую вилку uiUpdater.updateForkState(id, "left", true); rightFork.pickUp(); // Берет правую вилку uiUpdater.updateForkState(id, "right", true); eat(); // Философ ест leftFork.putDown(); // Возвращает левую вилку uiUpdater.updateForkState(id, "left", false); rightFork.putDown(); // Возвращает правую вилку uiUpdater.updateForkState(id, "right", false); waiter.releaseForks(); // Сообщает официанту об освобождении вилок } sleep(); // Философ спит } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }

DiningPhiloshoperGUI.java

package diningphilosophers; import javax.swing.*; import java.awt.*; import java.util.HashMap; import java.util.Map; // Класс DiningPhilosophersGUI представляет графический интерфейс для отображения состояния философов и вилок public class DiningPhilosophersGUI extends JFrame implements UIUpdater { private static final int NUM_PHILOSOPHERS = 5; // Количество философов private static final int IMAGE_SIZE = 50; // Размер изображений private final JLabel[] philosopherLabels = new JLabel[NUM_PHILOSOPHERS]; // Метки для отображения состояния философов private final JLabel[] leftForkLabels = new JLabel[NUM_PHILOSOPHERS]; // Метки для левых вилок private final JLabel[] rightForkLabels = new JLabel[NUM_PHILOSOPHERS]; // Метки для правых вилок private final Map<String, ImageIcon> images = new HashMap<>(); // Карта для хранения изображений public DiningPhilosophersGUI() { setTitle("Dining Philosophers"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(new GridBagLayout()); // Загрузка и масштабирование изображений ClassLoader classLoader = getClass().getClassLoader(); images.put("thinking", new ImageIcon(scaleImage(new ImageIcon(classLoader.getResource("thinking.png")).getImage(), IMAGE_SIZE, IMAGE_SIZE))); images.put("eating", new ImageIcon(scaleImage(new ImageIcon(classLoader.getResource("eating.png")).getImage(), IMAGE_SIZE, IMAGE_SIZE))); images.put("sleeping", new ImageIcon(scaleImage(new ImageIcon(classLoader.getResource("sleeping.png")).getImage(), IMAGE_SIZE, IMAGE_SIZE))); images.put("fork", new ImageIcon(scaleImage(new ImageIcon(classLoader.getResource("fork.png")).getImage(), IMAGE_SIZE, IMAGE_SIZE))); GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = new Insets(5, 5, 5, 5); gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 2; gbc.anchor = GridBagConstraints.CENTER; // Добавление меток философов for (int i = 0; i < NUM_PHILOSOPHERS; i++) { philosopherLabels[i] = new JLabel("Philosopher " + (i + 1)); philosopherLabels[i].setIcon(images.get("thinking")); gbc.gridy = i; add(philosopherLabels[i], gbc); } // Добавление меток левых вилок gbc.gridwidth = 1; gbc.gridx = 2; for (int i = 0; i < NUM_PHILOSOPHERS; i++) { leftForkLabels[i] = new JLabel(); gbc.gridy = i; add(leftForkLabels[i], gbc); } // Добавление меток правых вилок gbc.gridx = 3; for (int i = 0; i < NUM_PHILOSOPHERS; i++) { rightForkLabels[i] = new JLabel(); gbc.gridy = i; add(rightForkLabels[i], gbc); } setSize(800, 400); setVisible(true); } // Метод для масштабирования изображения private Image scaleImage(Image srcImg, int w, int h) { return srcImg.getScaledInstance(w, h, Image.SCALE_SMOOTH); } // Метод для обновления состояния философа @Override public void updatePhilosopherState(int id, String state) { SwingUtilities.invokeLater(() -> { if (state.contains("Eating")) { philosopherLabels[id].setIcon(images.get("eating")); } else if (state.contains("Thinking")) { philosopherLabels[id].setIcon(images.get("thinking")); } else if (state.contains("Sleeping")) { philosopherLabels[id].setIcon(images.get("sleeping")); } philosopherLabels[id].setText("Philosopher " + (id + 1) + ": " + state); }); } // Метод для обновления состояния вилки @Override public void updateForkState(int philosopherId, String forkPosition, boolean isPickedUp) { SwingUtilities.invokeLater(() -> { JLabel forkLabel = forkPosition.equals("left") ? leftForkLabels[philosopherId] : rightForkLabels[philosopherId]; if (isPickedUp) { forkLabel.setIcon(images.get("fork")); } else { forkLabel.setIcon(null); } }); } public static void main(String[] args) { DiningPhilosophersGUI gui = new DiningPhilosophersGUI(); // Создание графического интерфейса Waiter waiter = new Waiter(NUM_PHILOSOPHERS); // Создание официанта Fork[] forks = new Fork[NUM_PHILOSOPHERS]; // Создание вилок Philosopher[] philosophers = new Philosopher[NUM_PHILOSOPHERS]; // Создание философов for (int i = 0; i < NUM_PHILOSOPHERS; i++) { forks[i] = new Fork(); // Инициализация вилок } for (int i = 0; i < NUM_PHILOSOPHERS; i++) { Fork leftFork = forks[i]; // Левая вилка философа Fork rightFork = forks[(i + 1) % NUM_PHILOSOPHERS]; // Правая вилка философа philosophers[i] = new Philosopher(i, leftFork, rightFork, waiter, gui); // Создание философа philosophers[i].start(); // Запуск философа } } }

Соседние файлы в папке ЛАБЫ