请帮助我解决这个分为两部分的问题。这是第一部分:

(第2部分:自从-需求已更改
位。)

我正在尝试用Java实现图书馆员问题。 Wikipedia上的Semaphore page提供了信号量库的类比。在第一部分中,我试图为这个问题建模。就我而言,我使用的是[主题专家]而不是房间作为资源。

假设一个图书馆有10个相同的学习室,打算一次供一个学生使用。为避免纠纷,如果学生想使用自修室,必须向前台索取房间。当学生使用完一个房间后,必须返回柜台并指出其中一个房间已经免费。如果没有空余的房间,学生们将在柜台前等待,直到有人放弃房间。

由于房间是相同的,前台的图书管理员不会跟踪哪个房间被占用,只会跟踪可用的免费房间数。当学生要求一个房间时,图书馆员会减少这个数字。当学生放出房间时,图书馆员会增加这个数字。一旦准许进入房间,该房间就可以使用所需的长时间,因此不可能提前预订房间。

我在实施过程中面临的问题是有关学生与主题专家的关联。在接下来的 class 中,您将如何做? SubjectMatterExpert需要做的只是打印学生ID(目前)。

第2部分:新要求:
-有固定数量的学生,中小企业和书橱
-学生一开始有一定数量的书籍(目前,书籍只是数字)
-中小企业应学生的要求从Boook壁橱添加或签出书籍
-学生指定添加或签出操作,书的数量以及书柜

这是经过修改(编辑)的Student类:

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
    }
}

这是修改(编辑)的Simulator类:
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();
    }
}

这是(新的)书柜类:
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;
    }
}

最佳答案

在您描述的原始图书管理员问题中,该问题并不关心哪个学生在哪个房间中,因此使用简单的线程安全计数器(即信号量)来实现对资源的控制。在描述问题之后,仍然需要对实现进行更改。一种方法是对图书馆员使用两种方法,一种用于请求SME,另一种用于返还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);
         }
     }
}

07-26 09:29