4

请帮我解决这个由两部分组成的问题。这是第一部分:

(第 2 部分:我已经更新了代码 - 要求发生了一些变化。)

我正在尝试在 Java 中实现图书管理员问题。维基百科上的Semaphore 页面给出了 Semaphore 的类比库。在第一部分,我试图模拟这个问题。就我而言,我使用的是 [主题专家] 而不是房间作为资源。

假设一个图书馆有 10 个相同的自习室,打算一次只供一个学生使用。为防止发生纠纷,学生如果想使用自习室,必须向前台申请房间。当学生用完一个房间后,学生必须回到柜台并指出一个房间已经空闲。如果没有空房间,学生会在柜台等待,直到有人让出房间。

由于房间是相同的,前台的图书管理员不会记录哪个房间被占用,只记录可用房间的数量。当学生请求一个房间时,图书管理员会减少这个数字。当学生释放一个房间时,图书管理员会增加这个数字。一旦获得进入房间的权限,房间就可以根据需要使用多久,因此无法提前预订房间。

我在实施中面临的问题是关于学生与主题专家的关联。在接下来的 secnario 中,您将如何做到这一点?所需SubjectMatterExpert要做的就是打印学生 ID(现在)。

第 2 部分:新要求:
- 有固定数量的学生、SME 和书柜
- 学生在开始时有一定数量的书籍(目前,书籍只是数字)
- SME 在书柜中添加或签出书籍学生的请求
- 学生指定添加或签出操作、书籍数量和书柜

这是修改(编辑)的学生类:

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

2 回答 2

1

在您描述的原始图书馆员问题中,该问题不关心哪个学生在哪个房间,因此使用简单的线程安全计数器(即信号量)来实现对资源的控制。在对问题的描述之后,仍然需要更改您的实现。一种方法是在图书馆员类上使用两种方法,一种用于请求 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);
         }
     }
}
于 2011-03-21T14:51:18.810 回答
0

将 SME 作为线程在 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
    }
}

实施并与论坛中的其他人仔细检查。我刚来这地方。不过,更有经验的声音可能会有更好的发言权。希望这最终会有所帮助(= 不会造成伤害)。

于 2011-03-23T02:07:26.773 回答