2015-08-13 23:54:40 +02:00
|
|
|
|
---
|
|
|
|
|
layout: pattern
|
|
|
|
|
title: Object Pool
|
|
|
|
|
folder: object-pool
|
2015-08-15 18:03:05 +02:00
|
|
|
|
permalink: /patterns/object-pool/
|
2015-08-20 21:40:07 +02:00
|
|
|
|
categories: Creational
|
2021-05-19 10:49:05 -06:00
|
|
|
|
language: en
|
2015-12-28 15:52:44 +02:00
|
|
|
|
tags:
|
2019-12-13 21:09:28 +02:00
|
|
|
|
- Game programming
|
2015-12-28 16:07:43 +02:00
|
|
|
|
- Performance
|
2015-08-13 23:54:40 +02:00
|
|
|
|
---
|
|
|
|
|
|
2020-09-26 13:01:58 +03:00
|
|
|
|
## Also known as
|
|
|
|
|
|
|
|
|
|
Resource Pool
|
|
|
|
|
|
2016-01-03 21:14:30 +01:00
|
|
|
|
## Intent
|
2020-08-29 22:13:55 +03:00
|
|
|
|
|
|
|
|
|
When objects are expensive to create and they are needed only for short periods of time it is
|
|
|
|
|
advantageous to utilize the Object Pool pattern. The Object Pool provides a cache for instantiated
|
|
|
|
|
objects tracking which ones are in use and which are available.
|
2015-08-13 23:54:40 +02:00
|
|
|
|
|
2020-07-18 10:51:02 +03:00
|
|
|
|
## Explanation
|
|
|
|
|
|
|
|
|
|
Real world example
|
|
|
|
|
|
2020-08-29 22:13:55 +03:00
|
|
|
|
> In our war game we need to use oliphaunts, massive and mythic beasts, but the problem is that they
|
|
|
|
|
> are extremely expensive to create. The solution is to create a pool of them, track which ones are
|
|
|
|
|
> in-use, and instead of disposing them re-use the instances.
|
2020-07-18 10:51:02 +03:00
|
|
|
|
|
|
|
|
|
In plain words
|
|
|
|
|
|
|
|
|
|
> Object Pool manages a set of instances instead of creating and destroying them on demand.
|
|
|
|
|
|
|
|
|
|
Wikipedia says
|
|
|
|
|
|
2020-08-29 22:13:55 +03:00
|
|
|
|
> The object pool pattern is a software creational design pattern that uses a set of initialized
|
|
|
|
|
> objects kept ready to use – a "pool" – rather than allocating and destroying them on demand.
|
2020-07-18 10:51:02 +03:00
|
|
|
|
|
|
|
|
|
**Programmatic Example**
|
|
|
|
|
|
2020-08-29 22:13:55 +03:00
|
|
|
|
Here's the basic `Oliphaunt` class. These giants are very expensive to create.
|
2020-07-18 10:51:02 +03:00
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public class Oliphaunt {
|
|
|
|
|
|
2020-07-30 20:28:47 +03:00
|
|
|
|
private static final AtomicInteger counter = new AtomicInteger(0);
|
2020-07-18 10:51:02 +03:00
|
|
|
|
|
|
|
|
|
private final int id;
|
|
|
|
|
|
|
|
|
|
public Oliphaunt() {
|
|
|
|
|
id = counter.incrementAndGet();
|
|
|
|
|
try {
|
|
|
|
|
Thread.sleep(1000);
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int getId() {
|
|
|
|
|
return id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String toString() {
|
|
|
|
|
return String.format("Oliphaunt id=%d", id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2020-08-29 22:13:55 +03:00
|
|
|
|
Next we present the `ObjectPool` and more specifically `OliphauntPool`.
|
2020-07-18 10:51:02 +03:00
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public abstract class ObjectPool<T> {
|
|
|
|
|
|
2020-07-30 20:28:47 +03:00
|
|
|
|
private final Set<T> available = new HashSet<>();
|
|
|
|
|
private final Set<T> inUse = new HashSet<>();
|
2020-07-18 10:51:02 +03:00
|
|
|
|
|
|
|
|
|
protected abstract T create();
|
|
|
|
|
|
|
|
|
|
public synchronized T checkOut() {
|
|
|
|
|
if (available.isEmpty()) {
|
|
|
|
|
available.add(create());
|
|
|
|
|
}
|
|
|
|
|
var instance = available.iterator().next();
|
|
|
|
|
available.remove(instance);
|
|
|
|
|
inUse.add(instance);
|
|
|
|
|
return instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public synchronized void checkIn(T instance) {
|
|
|
|
|
inUse.remove(instance);
|
|
|
|
|
available.add(instance);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public synchronized String toString() {
|
|
|
|
|
return String.format("Pool available=%d inUse=%d", available.size(), inUse.size());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class OliphauntPool extends ObjectPool<Oliphaunt> {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected Oliphaunt create() {
|
|
|
|
|
return new Oliphaunt();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2020-08-29 22:13:55 +03:00
|
|
|
|
Finally, here's how we utilize the pool.
|
2020-07-18 10:51:02 +03:00
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
var pool = new OliphauntPool();
|
|
|
|
|
var oliphaunt1 = pool.checkOut();
|
|
|
|
|
var oliphaunt2 = pool.checkOut();
|
|
|
|
|
var oliphaunt3 = pool.checkOut();
|
|
|
|
|
pool.checkIn(oliphaunt1);
|
|
|
|
|
pool.checkIn(oliphaunt2);
|
|
|
|
|
var oliphaunt4 = pool.checkOut();
|
|
|
|
|
var oliphaunt5 = pool.checkOut();
|
|
|
|
|
```
|
|
|
|
|
|
2020-08-29 22:13:55 +03:00
|
|
|
|
Program output:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Pool available=0 inUse=0
|
|
|
|
|
Checked out Oliphaunt id=1
|
|
|
|
|
Pool available=0 inUse=1
|
|
|
|
|
Checked out Oliphaunt id=2
|
|
|
|
|
Checked out Oliphaunt id=3
|
|
|
|
|
Pool available=0 inUse=3
|
|
|
|
|
Checking in Oliphaunt id=1
|
|
|
|
|
Checking in Oliphaunt id=2
|
|
|
|
|
Pool available=2 inUse=1
|
|
|
|
|
Checked out Oliphaunt id=2
|
|
|
|
|
Checked out Oliphaunt id=1
|
|
|
|
|
Pool available=0 inUse=3
|
|
|
|
|
```
|
|
|
|
|
|
2019-12-07 20:01:13 +02:00
|
|
|
|
## Class diagram
|
2020-08-29 22:13:55 +03:00
|
|
|
|
|
2015-08-13 23:54:40 +02:00
|
|
|
|

|
|
|
|
|
|
2016-01-03 21:14:30 +01:00
|
|
|
|
## Applicability
|
2020-08-29 22:13:55 +03:00
|
|
|
|
|
2016-01-03 21:14:30 +01:00
|
|
|
|
Use the Object Pool pattern when
|
2015-08-13 23:54:40 +02:00
|
|
|
|
|
2020-08-29 22:13:55 +03:00
|
|
|
|
* The objects are expensive to create (allocation cost).
|
|
|
|
|
* You need a large number of short-lived objects (memory fragmentation).
|