The problem of allocating library resources using Semaphore in Java

Please help me with this two-part question. Here is the first part:

(Part 2: I updated the code since then - the requirements have changed a bit.)

I am trying to implement a library problem in Java. The Wikipedia Semaphore page provides a library analogy to Semaphore. In the first part, I try to simulate this problem. In my case, I use [Topic Expert] instead of a room as a resource.

Suppose the library has 10 identical classrooms designed for use by one student at a time. To prevent controversy, students should request a room from the front desk if they want to use the study. When the student has finished using the room, the student should return to the counter and indicate that one room has become free. If there are no rooms available, students wait at the counter until someone leaves the room.

Since the numbers are identical, the librarian at the reception does not keep track of which room is occupied, only the number of rooms available. When a student requests a room, the librarian decreases this number. When a student releases a room, the librarian increases this number. After access to the room is granted, the room can be used as long as possible, and therefore it is not possible to book rooms in advance.

The problem that I encountered in my implementation concerns the association of a student with a subject matter expert. How will you do this in the next secnario? All SubjectMatterExpert needs to do is print the student ID (for now).

Part 2: New Requirements:
- There is a fixed number of students, small and medium enterprises and bookcases
- Students have a certain number of books at the beginning (currently books are just numbers)
- SMEs add or check books from the Boook cabinet upon student request
- Students specify the action or number of copies, number of books, and bookcase

This is a modified (edited) Student class:

 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(); } } } 

This is a modified (edited) librarian class:

 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) //ie, 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(); } } } 

This is a modified (edited) Subject Matter Expert class:

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

This is a modified (edited) simulator class:

 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(); } } 

a is the (new) Book Closet class:

 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
source share
2 answers

In the original librarian problem that you described, the problem does not care about which student is in which room, therefore, uses a simple thread-safe counter (i.e. a semaphore) to exercise control over resources. Following this description of the problem, you still need to change your implementation. One approach is to use two methods in the class of librarians, one for querying the SME, the other for returning it.

 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(); } } } 

However, if you need to know which Student works with which SME, then you need a different design for managing resources, Semaphore is no longer enough. One example would be a lineup.

 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); } } } 
+1
source

It makes sense to have SMEs as threads running in a while loop. Check out some start codes below. In addition, you need to initialize the bookcase somewhere at the beginning of the simulation. I don't know the whole approach that you take, though.

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

Deploy and double-check with others in the forum. I'm new here. However, more experienced voices may have a better word. Hope this helps (= doesn't hurt) in the end.

0
source

Source: https://habr.com/ru/post/1344559/


All Articles