Java中带信号量的图书馆员资源分配问题
请帮我回答这个由两部分组成的问题。以下是第一部分: (第2部分:我已经更新了代码-要求已更改 位。) 我试图用Java实现图书管理员问题。Wikipedia上的标签给出了信号量的图书馆类比。在第一部分中,我试图对这个问题进行建模。在我的例子中,我使用[主题专家]而不是房间作为资源 假设一个图书馆有10个相同的自习室,一次供一个学生使用。为了避免争议,如果学生希望使用自修室,必须向前台申请一个房间。学生使用完房间后,必须返回柜台,并指出有一个房间已空闲。如果没有空房间,学生们就在柜台前等待,直到有人让出房间 由于房间是相同的,前台的图书管理员不记录哪个房间被占用,只记录可用的免费房间的数量。当学生要求一个房间时,图书管理员会减少这个数字。当学生释放一个房间时,图书管理员会增加这个数字。一旦获准进入某个房间,该房间就可以按需要使用多长时间,因此不可能提前预订房间 我在实施过程中面临的问题是关于学生与主题专家的关联。在接下来的几天里你会怎么做?Java中带信号量的图书馆员资源分配问题,java,semaphore,thread-synchronization,Java,Semaphore,Thread Synchronization,请帮我回答这个由两部分组成的问题。以下是第一部分: (第2部分:我已经更新了代码-要求已更改 位。) 我试图用Java实现图书管理员问题。Wikipedia上的标签给出了信号量的图书馆类比。在第一部分中,我试图对这个问题进行建模。在我的例子中,我使用[主题专家]而不是房间作为资源 假设一个图书馆有10个相同的自习室,一次供一个学生使用。为了避免争议,如果学生希望使用自修室,必须向前台申请一个房间。学生使用完房间后,必须返回柜台,并指出有一个房间已空闲。如果没有空房间,学生们就在柜台前等待,直到有
SubjectMatterExpert
需要做的就是打印学生Id(目前)
第2部分:新要求:-有固定数量的学生、中小企业和书柜
-学生开始时有一定数量的书(目前,书只是数字)
-SME根据学生的要求从book壁橱中添加或检出书籍
-学生指定添加或签出操作、书籍数量和书架 这是修改(编辑)的学生课堂:
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;
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 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;
}
}
这是已修改(编辑)的图书管理员类:
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 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();
}
}
在您描述的原始图书管理员问题中,该问题不关心哪个学生在哪个房间,因此使用一个简单的线程安全计数器(即信号量)来实现对资源的控制。根据对问题的描述,仍然需要对实现进行更改。一种方法是在Library类上使用两种方法,一种用于请求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);
}
}
}
班级图书馆员{
阻塞队列q=
新的ArrayBlockingQueue(SME的数量);
公共图书馆员(){
对于(int i=0;i
让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
}
}
执行并与论坛中的其他人再次核实。我是新来的。不过,更有经验的声音可能会有更好的发言权。希望这会有所帮助(=不会伤害)最后。+1感谢您为写这样的文章所付出的努力,并解释清楚question@SurajChandran谢谢你,苏拉杰。这是我在这里的第一篇文章,我想从头开始。我希望在这里得到这个项目的一些方向-似乎我对这个问题的理解和它的实现完全偏离了轨道。(希望不是)Michael,非常感谢您的详细解释。在我开始进一步实验之前,请先做一个简短的观察:一旦学生被分配到SME,SME将代表学生运行一系列任务(问题的第2部分详细说明).完成任务后,图书管理员队列如何知道将SME添加回队列?SME类是否会调用ReleaseSEM(),将自己传递给方法?这是一个安全的电话吗?再次感谢您的回答!非常感谢。我将把发布SME的责任留给学生。学生可以问SME的问题,然后在完成后将SME返回给图书管理员。我不会让SME作为线程运行,只是代表工作作为一个简单的方法调用为学生完成。Michael,我理解你为什么建议学生释放SME。这很有道理。但我将SME作为一个线程运行的原因可能与我在原始问题中发布的问题的第二部分有关。本质上,我不希望不必要的上下文switc学生之间的兴-因此,我想运行SME线程,让它在等待下一个学生时“休眠”。如果我遗漏了一点,请告知。