Using reusable objects/resources as a pool in Java is very common. In fact, the Java language itself comes with built-in thread-pool support. In this article, we will demonstrate how we can create a custom resource pool in Java.
What is a Resource pool?
A resource pool is a collection of reusable resources that can be shared among multiple clients or consumers in a Java application. Resources are borrowed when needed and put back when usage is complete.
Why do you need a resource pool?
Creating and initializing classes can often be very expensive and slow. Creating a custom resource pool can be useful when you need to manage a limited number of expensive or scarce resources, such as database connections or other custom task threads that are usually expensive to initialize on demand.
How do we create a resource pool?
To keep things very simple for this post, we will be creating two different classes:
- Resource class – The resource itself
- ResourcePool class – manages and maintains a fixed limited number of resource
Resource:
First, let’s create a simple new Resource class representing the resource we want to manage. The methods “acquire”/”release”/”close” etc. aren’t necessarily needed, but this convention would help maintain the integrity of the resources and keep them error-free (e.g., resources are still referenced even after being released, etc.). Ideally, an interface definition for enforcing such policies would be more appropriate.
public class Resource {
private String id;
public Resource(String id) {
this.id = id;
}
public boolean acquire() {
System.out.println("Resource being acquired: "+id);
// Blocks until a resource is available
return true;
}
public boolean release() {
System.out.println("Released resource: "+id);
return true;
}
public void close() {
System.out.println("Resource being shut down: "+id);
}
}
Code language: PHP (php)
ResourcePool:
Next, let’s create the ResourcePool class that will manage a collection of Resource objects. Three most important methods for this class are: acquire(), release(), and shutdown(). In practice, it might be a good idea to wrap them around a generic interface definition for clarity. The acquire() method will be used by clients to get a Resource object from the pool, the release() method will be used to return the Resource to the pool when it is no longer needed, and the shutdown() method will be used to clean up the resource pool when it is being shutdown etc.
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.Supplier;
public class ResourcePool {
private final BlockingQueue<Resource> resourcePool;
public ResourcePool(int size, Supplier<Resource> resourceFactory) {
this.resourcePool = new LinkedBlockingQueue<>(size);
// Fill the resourcePool with resources
// Can be differed and filled on-demand when pool is empty as well
for (int i = 0; i < size; i++) {
resourcePool.add(resourceFactory.get());
}
}
public Resource acquire() throws InterruptedException {
// Blocks until a resource is available
Resource resource = resourcePool.take();
resource.acquire();
return resource;
}
public void release(Resource resource) {
// Release the resource back to the pool
resource.release();
resourcePool.offer(resource);
}
public void shutdown() {
// Close all the resources in the pool
while (!resourcePool.isEmpty()) {
Resource resource = resourcePool.poll();
if (resource != null) {
resource.close();
}
}
}
}
Code language: PHP (php)
Make sure to pay attention to the ‘BlockingQueue<Resource>’ data type we use here as our data structure choice. This is crucial due to the concurrent need for access from multiple threads. It automatically takes care of concurrent access with its internal locking mechanism for you.
Using the pool:
Now that we have defined the Resource and ResourcePool classes, we can use them in our application. Here is an example piece of code about how to use the above-defined resource pool:
public static void main(String[] args) {
// Create a resource pool with 10 connections
ResourcePool pool = new ResourcePool(10, () -> {
// Create and return a new connection
return new Resource(UUID.randomUUID().toString());
});
// Acquire a resource from the pool
Resource resource;
try {
resource = pool.acquire();
//TODO: Use the resource
// ...
// Release the resource back to the pool
pool.release(resource);
// Shut down the resource pool
pool.shutdown();
} catch (InterruptedException err) {
//
}
}
Code language: JavaScript (javascript)
Conclusion:
You don’t necessarily always create such a custom resource pool in Java; instead, you should be able to reuse open-source libraries like Apache Commons Pool. But if, for whatever reason, you are unable to do so and/or you have some custom need that can’t be met otherwise, knowing how to create a custom pool yourself could be very handy.
Discover more from CodeSamplez.com
Subscribe to get the latest posts sent to your email.
Leave a Reply