Проблема выделения ресурсов библиотекаря с семафором в Java - PullRequest
4 голосов
/ 21 марта 2011

Пожалуйста, помогите мне с этим вопросом из двух частей.Вот первая часть:

(Часть 2: с тех пор я обновил код - требования немного изменились.)

Япытаясь реализовать проблему библиотекаря в Java.Страница Семафор в Википедии дает библиотечную аналогию Семафора.В первой части я пытаюсь смоделировать эту проблему.В моем случае я использую [Subject Matter Expert] вместо комнаты в качестве ресурса.

Предположим, в библиотеке есть 10 идентичных учебных комнат, предназначенных для использования одним студентом одновременно.Чтобы предотвратить споры, студенты должны запросить комнату у стойки регистрации, если они хотят использовать учебную комнату.Когда студент закончил пользоваться комнатой, он должен вернуться к прилавку и указать, что одна комната стала свободной.Если ни одна из комнат не свободна, студенты ждут у стойки, пока кто-нибудь не освободит комнату.

Поскольку комнаты идентичны, библиотекарь на стойке регистрации не отслеживает, какая комната занята, только количество свободныхномера доступны.Когда студент запрашивает комнату, библиотекарь уменьшает это число.Когда студент освобождает комнату, библиотекарь увеличивает это число.Как только доступ к комнате предоставлен, комнату можно использовать столько времени, сколько необходимо, и поэтому невозможно забронировать номера заранее.

Проблема, с которой я сталкиваюсь в своей реализации, заключается в том, чтооб ассоциации студента с экспертом по предмету.Как бы вы сделали это в следующем разделе?Все, что нужно SubjectMatterExpert, - это распечатать Идентификатор студента (на данный момент).

Часть 2. Новые требования:
- Есть фиксированное количество студентов, МСП,и Книжные шкафы
- Ученики имеют определенное количество Книг в начале (в настоящее время книги - просто числа)
- МСП добавляют или проверяют книги из Шкафчика Boook по просьбе Студента
- Студенты указывают добавить илидействие проверки, количество книг и шкаф для книг

Это модифицированный (отредактированный) класс ученика:

package librarysimulation;

public class Student extends Thread {

    String studentId = "";
    Librarian librarian = null;
    int bookCount = 0;

    public Student(String id, Librarian lib, int book) {
        studentId = id;
        librarian = lib;
        bookCount = book;
    }

    @Override
    public void run() {

        System.out.println("Student " + studentId + " is requesting SME...");
        librarian.requestSME();

        try {
            // Do something
            System.out.println("Student " + studentId + " has access to an SME.");
            //How do I ask the SME to add OR checkOut 'x' number of books
            //from a given BookCloset?
        } finally {
            librarian.releaseSME();
        }
    }
}

Это модифицированный (отредактированный)Класс библиотекаря:

package librarysimulation;

import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Librarian {

    public Semaphore sme;
    public int bookClosetCount = 0;

    public Librarian(int smeCount, int bookCloset) {
        sme = new Semaphore(smeCount, true);
        bookClosetCount = bookCloset;
        //openLibrary(smeCount);
    }

    //Receive SME request from the Student here
    public void requestSME() {
        try {
            sme.acquire();
            //assign student to SME
        } catch (InterruptedException ex) {
            Logger.getLogger(Librarian.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    //Release SME from the Student here
    public void releaseSME() {
        sme.release();//release SME
    }

    //Set the SME threads active (from constructor)
    //i.e., when the library opens, have the SMEs ready
    public final void openLibrary(int roomCount) {
        for (int i = 0; i < roomCount; i++) {
            SubjectMatterExpert s = new SubjectMatterExpert(String.valueOf(i));
            s.start();
        }
    }
}

Это модифицированный (отредактированный) предметный экспертный класс:

package librarysimulation;

public class SubjectMatterExpert extends Thread {
    String smeId = "";
    SubjectMatterExpert(String id) {
        smeId = id;
    }

    @Override
    public void run(){

        //Handle Student request
        //Students specify if they are checking out books or returning books
        //Students specify number of books
        //Students specify which closet

        //SME simply executes the method from the Book Closet instance
    }
}

Это модифицированный (отредактированный) класс симулятора:

package librarysimulation;

public class Simulator extends Thread {

    public static final int STUDENT_COUNT = 50;
    public static final int SME_COUNT = 3;
    public static final int BOOKCLOSET_COUNT = 10;
    public static final int BOOK_PER_STUDENT_COUNT = 10;

    @Override
    public void run() {
        //Instantiate Library//New library with 3 SMEs
        Librarian lib = new Librarian(SME_COUNT, BOOKCLOSET_COUNT);
        //Create students
        int i = 0;
        while (i < STUDENT_COUNT) {
            Student s = new Student(String.valueOf(i), lib, BOOK_PER_STUDENT_COUNT);
            s.start();
            i++;
        }
    }

    public static void main(String[] args) {
        Simulator s = new Simulator();
        s.start();
    }
}

и это (новый) класс Book Closet:

package librarysimulation;

public class BookCloset {

    int closetId;
    int bookCount = 0;

    public BookCloset(int id, int book) {
        closetId = id;
        bookCount = book;
    }

    public int addBook(int book){
        return bookCount + book;
    }

    public int checkOutBook(int book){
        int finalBookCount = bookCount - book;
        //Change book count iff it makes sense to do so
        if(finalBookCount >= 0)
            bookCount = finalBookCount;
        //If return value is -ve, handle accordingly
        return finalBookCount;
    }
}

Ответы [ 2 ]

1 голос
/ 21 марта 2011

В исходной задаче библиотекаря, которую вы описали, этой проблеме не важно, какой студент находится в какой комнате, поэтому он использует простой потокобезопасный счетчик (то есть семафор) для реализации контроля над ресурсами. После этого описания проблемы все еще должно быть изменение вашей реализации. Один из подходов состоит в том, чтобы использовать 2 метода в классе библиотекаря: один для запроса SME, другой для его возврата.

class Librarian {
    Semaphore sme = new Semaphore(NUMBER_OF_SMES);

    void requestSme() throws InterruptedException {
        sme.acquire();
    }

    void releaseSme() {
        sme.release();
    }
}

 class Student {
     Librarian librarian;

     public void run() {

         libarian.requestSme();
         try {
             // Do something
         finally {
             librarian.releaseSme();
         }
     }
}

Однако, если вам нужно знать, с каким студентом работает какой SME, вам понадобится другая конструкция для управления ресурсами, семафора больше не достаточно. Одним из примеров может быть Очередь.

class Librarian {
    BlockingQueue<SubjectMatterExpert> q = 
        new ArrayBlockingQueue<SubjectMatterExpert>(NUMBER_OF_SMES);

    public Librarian() {
        for (int i = 0; i < NUMBER_OF_SMES; i++)
            q.put(new SubjectMatterExpert(String.valueOf(i));
    } 

    SubjectMatterExport requestSme() throws InterruptedException {
        q.take();
    }

    void releaseSme(SubjectMatterExpert toRelease) {
        q.put(toRelease);
    }
}

 class Student {
     Librarian librarian;

     public void run() {

         SubjectMatterExpert sme = libarian.requestSme();
         try {
             System.out.println("Student: " + this + ", SME: " sme);
         finally {
             if (sme != null)
                 librarian.releaseSme(sme);
         }
     }
}
0 голосов
/ 23 марта 2011

Имеет смысл иметь МСП в качестве потоков, работающих в цикле while. Проверьте некоторые стартовые коды ниже. Также вам нужно инициализировать книжный шкаф где-то в начале симуляции. Хотя я не знаю, какой подход вы используете.

package librarysimulation;

public class SubjectMatterExpert extends Thread {
    String smeId = "";
    SubjectMatterExpert(String id) {
        smeId = id;
    }

    @Override
    public void run(){

        while(true){
        //acquire a student (semaphor)
        //acquire a lock (semaphor(1))
             //critical region - 
             //Handle Student request
             //Students specify if they are checking out books or returning books
             //Students specify number of books
             //Students specify which closet
        //release yourself (semaphor - define in library)
        //release lock (semaphor(1)) 

        }
        //SME simply executes the method from the Book Closet instance
    }
}

Реализация и двойная проверка с другими на форуме. Я здесь новичок. Более опытные голоса могут иметь лучшее мнение, хотя. Надеюсь, это поможет (= не повредит) в конце.

...