# ObjectPool

> ObjectPool is used to reuse objects across the application instead of creating new instances every time they are needed. It is based on a simple idea: objects are created once and then retrieved again using a shared identifier.

Each object is stored under a specific identifier. When you request an object with `ObjectPool.get`, the pool checks if an object already exists for that identifier. If it does, the same instance is returned. If it does not, the object is created using the provided factory and stored for future use.

This removes the need to pass objects through multiple layers of code or manually manage shared instances.

{% hint style="info" %}
ObjectPool is mainly used for objects that should exist once per application context, such as thread pools, shared services, or other reusable components that are expensive or unnecessary to recreate multiple times.
{% endhint %}

***

### Object retrieval - `get`

`ObjectPool.get` returns an object stored in the pool for a given identifier.

```java
ObjectPool.get(String identifier, Supplier<T> objectFactory)
```

The `identifier` is used to locate an existing object. If an object already exists for that identifier, it is returned. If not, the `objectFactory` is executed once to create the object, and the result is stored under that identifier.

This ensures the same identifier always resolves to the same object for the lifetime of the application.

#### Sharing Objects - Example

When you call `ObjectPool.get` with the same identifier (for example `"executor"`), the first call uses the supplier `() -> Executors.newFixedThreadPool(4)` to create a new instance and store it internally. The next call with the same identifier returns the already created instance instead of creating a new one. This allows you to reuse the same object across different parts of the project without recreating it or introducing shared singleton classes.

```java
ExecutorService executor = ObjectPool.get("executor", () -> Executors.newFixedThreadPool(4));
ExecutorService sameExecutor = ObjectPool.get("executor", () -> Executors.newFixedThreadPool(4));

IO.println(Objects.equals(executor, sameExecutor)); // true

// Without ObjectPool
ExecutorService direct1 = Executors.newFixedThreadPool(4);
ExecutorService direct2 = Executors.newFixedThreadPool(4);

IO.println(Objects.equals(direct1, direct2)); // false
```

### All objects retrieval - `getAllExistingObjects`

`ObjectPool.getAllExistingObjects` returns all objects stored in the pool for a given type.

```java
ObjectPool.getAllExistingObjects(Class<T> objectType)
```

The `objectType` is used to filter objects by class. It returns every instance of that type that was previously created through `ObjectPool.get`.

The returned collection is unmodifiable and it's mainly used when you need to iterate through all instances of a type, for example during application shutdown to release resources.

#### Managing all executors - Example

All executors stored in the pool can be closed together:

```java
Collection<ExecutorService> executors = ObjectPool.getAllExistingObjects(ExecutorService.class);
for (ExecutorService executor : executors) {
  executor.shutdown();
}
```

***

### Lifetime of objects

{% hint style="info" %}
Objects in `ObjectPool` live for the full runtime of the application.
{% endhint %}

The objects are created once per identifier, when the `ObjectPool.get` method is invoked, and reused everywhere, stored as strong references. Since they are not automatically removed, cleanup must be done manually when the application stops.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ranked.wtf/core-concepts/objectpool.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
