Object Pool Design pattern comes under creational design patterns. This patter maintains a collection of limited number of objects (object pool) for reusability and to boost performance. This pattern is helpful in situations where the cost of creating new object is high and the frequency of object creation is also high but the number of objects in use is limited.
An Object Pool is a collection of limited number of objects. When one of the objects is in use, it will not be available in the pool till it has been released from the client.
For example, creating a database connection object affects the performance and should not be created in large numbers. In such cases we use this object pool design pattern which effectively reuses existing database connection objects.
Advantages:
- Improves performance because of the reusability of costly objects.
- Effectively manages the object pool to reuse and share existing objects among clients.
- The size of the object pool can also be configured.
Example:
Consider a scenario where, a hotel having a limited number of rooms and allow visitors to book the room based on the availability. Here hotel is the object pool contains limited number of rooms. Client can book a room through hotel reception. This hotel reception allocate room to a client based on the availability or let them wait till it will be available.
Creating Object Pool Class
Here the Hotel class is the object pool class which effectively manages the allocation and deallocation of rooms based on the availability and demand.
package com.learningupskills.designpattern.objectpool;
import java.util.HashSet;
import java.util.Set;
public class Hotel {
private static Set<Room> availableRooms = new HashSet<Room>();
private static Set<Room> roomsInUse = new HashSet<Room>();
private static Hotel hotelInstance;
private String hotelName;
private int totalRooms;
private Hotel(String hotelName, int noOfRooms) {
this.hotelName = hotelName;
this.totalRooms = noOfRooms;
Room.setHotel(this);
for (int i = 0; i < totalRooms; i++) {
Room room = new Room(i + 1);
availableRooms.add(room);
}
}
public static Hotel getHotelInstance(String hotelName, int totalRooms) {
if (hotelInstance == null) {
hotelInstance = new Hotel(hotelName, totalRooms);
System.out.println("Hotel Name :"+hotelInstance.hotelName +" with "+totalRooms+" Rooms\n");
}
return hotelInstance;
}
public synchronized void bookHotelRoom(String personName, long milliseconds) throws InterruptedException {
while (availableRooms.size() == 0) {
try {
System.out.println("All rooms are occupied, " + personName + " is waiting to get a room");
wait();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + "Interrupted.");
}
}
if (availableRooms.size() > 0) {
Room firstElement = availableRooms.stream().findFirst().get();
firstElement.setPersonOccupied(personName);
firstElement.setVacantAfter(milliseconds);
Thread newThread = new Thread(firstElement);
newThread.start();
System.out.println(personName + " is allocated with Room Number " + firstElement.getRoomNumber()
+ " for " + milliseconds + " milliseconds");
availableRooms.remove(firstElement);
roomsInUse.add(firstElement);
}
}
public synchronized void vocateHoteRoom(Room room) {
if (room != null && room.getPersonOccupied() != null) {
System.out.println(room.getPersonOccupied() + " is vacating Room Number " + room.getRoomNumber());
room.setPersonOccupied(null);
roomsInUse.remove(room);
availableRooms.add(room);
notifyAll();
}
}
}
Creating Room Class
Room class is the resource class. This Room objects will be created and managed by Hotel class.
package com.learningupskills.designpattern.objectpool;
import java.util.Objects;
public class Room implements Runnable{
private int roomNumber;
private String personOccupied;
private long vacantAfter;
private static Hotel hotel;
public static void setHotel(Hotel hotel) {
Room.hotel = hotel;
}
public Room(int roomNumber)
{
this.roomNumber = roomNumber;
}
public String getPersonOccupied() {
return personOccupied;
}
public void setPersonOccupied(String personOccupied) {
this.personOccupied = personOccupied;
}
public long getVacantAfter() {
return vacantAfter;
}
public void setVacantAfter(long vacantAfter) {
this.vacantAfter = vacantAfter;
}
public int getRoomNumber() {
return roomNumber;
}
@Override
public int hashCode() {
return Objects.hash(roomNumber);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Room other = (Room) obj;
return roomNumber == other.roomNumber;
}
@Override
public void run() {
try {
Thread.sleep(vacantAfter);
hotel.vocateHoteRoom(this);
}
catch (Exception e) {
hotel.vocateHoteRoom(this);
System.out.println(e.getMessage());
}
}
}
Creating Person class
Person class is the client class which wants to use the resource (room) of the Hotel.
package com.learningupskills.designpattern.objectpool;
public class Person{
private String personName;
private long timeNeeded;
public Person(String name, long stayTime)
{
this.timeNeeded =stayTime;
this.personName = name;
}
public String getPersonName() {
return personName;
}
public void setPersonName(String personName) {
this.personName = personName;
}
public long getTimeNeeded() {
return timeNeeded;
}
public void setTimeNeeded(long timeNeeded) {
this.timeNeeded = timeNeeded;
}
}
Creating HotelReception Class
HotelReception class is the main class which act as an intermediate class between object pool(Hotel) and client(Person)
package com.learningupskills.designpattern.objectpool;
import java.util.ArrayList;
import java.util.List;
public class HotelReception {
private List<Person> persons;
private static Hotel hotel;
public HotelReception(String hotelName, int totalRooms)
{
this.persons = new ArrayList<Person>();
hotel = Hotel.getHotelInstance(hotelName, totalRooms);
}
public void registerHotelRoom(Person person)
{
persons.add(person);
}
private void allocateHotelRooms() throws InterruptedException
{
for(Person person: persons)
{
hotel.bookHotelRoom(person.getPersonName(), person.getTimeNeeded());
}
}
public static void main(String[] args) {
HotelReception reception = new HotelReception("SPSN Resort", 4);
reception.registerHotelRoom(new Person("Amitabh", 5000));
reception.registerHotelRoom( new Person("Senthil Nathan", 7000));
reception.registerHotelRoom(new Person("John", 8000));
reception.registerHotelRoom(new Person("Rithik", 6000));
reception.registerHotelRoom(new Person("Surya", 10000));
reception.registerHotelRoom(new Person("Michael", 4000));
reception.registerHotelRoom(new Person("Alexandar", 9000));
try {
reception.allocateHotelRooms();
} catch (InterruptedException e) {
System.err.println("Allocation failure");
}
}
}
Result
Hotel Name :SPSN Resort with 4 Rooms
Amitabh is allocated with Room Number 1 for 5000 milliseconds
Senthil Nathan is allocated with Room Number 2 for 7000 milliseconds
John is allocated with Room Number 3 for 8000 milliseconds
Rithik is allocated with Room Number 4 for 6000 milliseconds
All rooms are occupied, Surya is waiting to get a room
Amitabh is vacating Room Number 1
Surya is allocated with Room Number 1 for 10000 milliseconds
All rooms are occupied, Michael is waiting to get a room
Rithik is vacating Room Number 4
Michael is allocated with Room Number 4 for 4000 milliseconds
All rooms are occupied, Alexandar is waiting to get a room
Senthil Nathan is vacating Room Number 2
Alexandar is allocated with Room Number 2 for 9000 milliseconds
John is vacating Room Number 3
Michael is vacating Room Number 4
Surya is vacating Room Number 1
Alexandar is vacating Room Number 2