Simplest Possible Usage
Stormpot has an invasive API which means that there is a minimum of things your code needs to do to use it. However, the requirements are quite benign, as this section is all about showing you.
The objects that you manage with a Stormpot pool needs to implement the Poolable
interface.
The absolute minimum amount of code required for its implementation is this:
// MyPoolable.java - minimum Poolable implementation
import stormpot.BasePoolable;
import stormpot.Slot;
public class MyPoolable extends BasePoolable {
public MyPoolable(Slot slot) {
super(slot);
}
}
We extend the BasePoolable
class, pass a Slot
argument through to its constructor, and leave the rest of the implementation to the BasePoolable
class.
We can also implement the Poolable
interface directly.
Here is an example of how to do this:
// MyOtherPoolable.java - explicit Poolable implementation
import stormpot.Poolable;
import stormpot.Slot;
public class MyOtherPoolable implements Poolable {
private final Slot slot;
public MyOtherPoolable(Slot slot) {
this.slot = slot;
}
@Override
public void release() {
slot.release(this);
}
}
The object in essence just needs to keep its Slot
instance around, and give itself as a parameter to the Slot#release
method.
Now that we have a class of objects to pool, we need some way to tell Stormpot how to create them.
We do this by implementing the Allocator
interface:
// MyAllocator.java - minimum Allocator implementation
import stormpot.Allocator;
import stormpot.Slot;
public class MyAllocator implements Allocator<MyPoolable> {
public MyPoolable allocate(Slot slot) throws Exception {
return new MyPoolable(slot);
}
public void deallocate(MyPoolable poolable) throws Exception {
// Nothing to do here
// But it's a perfect place to close sockets, files, etc.
}
}
That’s it.
Given a slot, create a MyPoolable
.
Or given a MyPoolable
, deallocate it.
And that is actually all the parts we need to start using Stormpot.
All that is left is a little bit of configuration:
Pool<MyPoolable> pool = Pool.from(new MyAllocator()).build();
Timeout timeout = new Timeout(1, TimeUnit.SECONDS);
MyPoolable object = pool.claim(timeout);
try {
// Do stuff with 'object'.
// Note that 'claim' will return 'null' if it times out!
} finally {
if (object != null) {
object.release();
}
}
We get a PoolBuilder
via the Pool.from
method, which takes an allocator.
Then we use it to build a pool with the configuration we want, and off we go!
The blocking methods Pool#claim
and Completion#await
both take Timeout
objects as arguments.
These are immutable, and can easily be put in static final
constants.
Note that claim
returns null
if the timeout elapses before an object can be claimed.
Also, using try-finally
is a great way to make sure that you don’t forget to release the objects back into the pool.
Stormpot cannot prevent objects from leaking in user code, so if you lose the reference to an object that hasn’t been released back into the pool, it will not come back on its own. Leaked objects can also cause problems with shutting the pool down, because the shut down procedure does not complete until all allocated objects are deallocated. So if you have leaked objects, shutting the pool down will never complete normally. You can still just halt the JVM, though.