Updated object pool to have Blocking, Non-Blocking, and Non-Blocking (soft references) pool types

This commit is contained in:
nathan 2016-03-05 15:29:46 +01:00
parent ef5e71d18a
commit 1a9e0bb8ac
6 changed files with 376 additions and 67 deletions

View File

@ -44,7 +44,7 @@ Usage:
<dependency>
<groupId>com.dorkbox</groupId>
<artifactId>ObjectPool</artifactId>
<version>2.1</version>
<version>2.2</version>
</dependency>
```

View File

@ -0,0 +1,84 @@
/*
* Copyright 2014 dorkbox, llc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dorkbox.objectPool;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/**
* @author dorkbox, llc
*/
class BlockingPool<T> extends ObjectPool<T> {
private final BlockingQueue<T> queue;
private final PoolableObject<T> poolableObject;
BlockingPool(PoolableObject<T> poolableObject, int size) {
this(poolableObject, new ArrayBlockingQueue<T>(size));
}
BlockingPool(final PoolableObject<T> poolableObject, final BlockingQueue<T> queue) {
this.poolableObject = poolableObject;
this.queue = queue;
for (int x = 0; x < queue.size(); x++) {
T e = poolableObject.create();
poolableObject.onReturn(e);
this.queue.add(e);
}
}
/**
* Takes an object from the pool, Blocks until an item is available in the pool.
* <p/>
* This method catches {@link InterruptedException} and discards it silently.
*/
public
T take() {
try {
return takeInterruptibly();
} catch (InterruptedException e) {
return null;
}
}
/**
* Takes an object from the pool, Blocks until an item is available in the pool.
*/
public
T takeInterruptibly() throws InterruptedException {
final T take = this.queue.take();
poolableObject.onTake(take);
return take;
}
/**
* Return object to the pool, waking the threads that have blocked during take()
*/
public
void put(T object) {
poolableObject.onReturn(object);
this.queue.offer(object);
}
/**
* @return a new object instance created by the pool.
*/
public
T newInstance() {
return poolableObject.create();
}
}

View File

@ -0,0 +1,78 @@
/*
* Copyright 2016 dorkbox, llc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dorkbox.objectPool;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* @author dorkbox, llc
*/
class NonBlockingPool<T> extends ObjectPool<T> {
private final Queue<T> queue;
private final PoolableObject<T> poolableObject;
NonBlockingPool(final PoolableObject<T> poolableObject) {
this(poolableObject, new ConcurrentLinkedQueue<T>());
}
NonBlockingPool(final PoolableObject<T> poolableObject, final Queue<T> queue) {
this.poolableObject = poolableObject;
this.queue = queue;
}
/**
* Takes an object from the pool, Blocks until an item is available in the pool.
*/
public
T take() {
T take = this.queue.poll();
if (take == null) {
take = poolableObject.create();
}
poolableObject.onTake(take);
return take;
}
/**
* Takes an object from the pool, Blocks until an item is available in the pool.
* <p/>
* This method catches {@link InterruptedException} and discards it silently.
*/
public
T takeInterruptibly() throws InterruptedException {
return take();
}
/**
* Return object to the pool, waking the threads that have blocked during take()
*/
public
void put(T object) {
poolableObject.onReturn(object);
this.queue.offer(object);
}
/**
* @return a new object instance created by the pool.
*/
public
T newInstance() {
return poolableObject.create();
}
}

View File

@ -0,0 +1,82 @@
/*
* Copyright 2016 dorkbox, llc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dorkbox.objectPool;
import java.lang.ref.SoftReference;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* @author dorkbox, llc
*/
class NonBlockingSoftPool<T> extends ObjectPool<T> {
private final Queue<SoftReference<T>> queue;
private final PoolableObject<T> poolableObject;
NonBlockingSoftPool(final PoolableObject<T> poolableObject) {
this(poolableObject, new ConcurrentLinkedQueue<SoftReference<T>>());
}
NonBlockingSoftPool(final PoolableObject<T> poolableObject, final Queue<SoftReference<T>> queue) {
this.poolableObject = poolableObject;
this.queue = queue;
}
/**
* Takes an object from the pool.
*/
public
T take() {
T obj;
SoftReference<T> ref;
while((ref = queue.poll()) != null) {
if((obj = ref.get()) != null) {
poolableObject.onTake(obj);
return obj;
}
}
final T take = poolableObject.create();
poolableObject.onTake(take);
return take;
}
/**
* Takes an object from the pool.
*/
public
T takeInterruptibly() throws InterruptedException {
return take();
}
/**
* Return object to the pool.
*/
public
void put(T object) {
poolableObject.onReturn(object);
this.queue.offer(new SoftReference<T>(object));
}
/**
* @return a new object instance created by the pool.
*/
public
T newInstance() {
return poolableObject.create();
}
}

View File

@ -15,86 +15,106 @@
*/
package dorkbox.objectPool;
import java.util.concurrent.ArrayBlockingQueue;
import java.lang.ref.SoftReference;
import java.util.Queue;
import java.util.concurrent.BlockingQueue;
/**
* @author dorkbox, llc
*/
public
class ObjectPool<T> {
private final ArrayBlockingQueue<T> queue;
private final PoolableObject<T> poolableObject;
public abstract
class ObjectPool<T> implements Pool<T> {
/**
* Gets the version number.
*/
public static
String getVersion() {
return "2.1";
}
public
ObjectPool(PoolableObject<T> poolableObject, int size) {
this.poolableObject = poolableObject;
this.queue = new ArrayBlockingQueue<T>(size);
for (int x = 0; x < size; x++) {
T e = poolableObject.create();
poolableObject.onReturn(e);
this.queue.add(e);
}
}
/**
* Takes an object from the pool, Blocks until an item is available in the pool.
*/
public
T take() throws InterruptedException {
final T take = this.queue.take();
poolableObject.onTake(take);
return take;
}
/**
* Takes an object from the pool, Blocks until an item is available in the pool.
* <p/>
* This method catches {@link InterruptedException} and discards it silently.
*/
@SuppressWarnings({"Duplicates", "SpellCheckingInspection"})
public
T takeUninterruptibly() {
try {
return take();
} catch (InterruptedException e) {
return null;
}
}
/**
* Return object to the pool, waking the threads that have blocked during take()
*/
public
void release(T object) {
poolableObject.onReturn(object);
this.queue.offer(object);
}
/**
* @return a new object instance created by the pool.
*/
public
T newInstance() {
return poolableObject.create();
return "2.2";
}
/**
* @return the number of currently pooled objects
* Creates a blocking pool of a specific size, where the entire pool is initially filled, and when the pool is empty, a
* {@link ObjectPool#take()} will wait for a corresponding {@link ObjectPool#put(Object)}.
*
* @param poolableObject controls the lifecycle of the pooled objects.
* @param size the size of the pool to create
* @param <T> the type of object used in the pool
*
* @return a blocking pool using the default ArrayBlockingQueue implementation of a specific size
*/
public
int size() {
return queue.size();
public static <T> ObjectPool<T> Blocking(PoolableObject<T> poolableObject, int size) {
return new BlockingPool<T>(poolableObject, size);
}
/**
* Creates a blocking pool of a specific size, where the entire pool is initially filled, and when the pool is empty, a
* {@link ObjectPool#take()} will wait for a corresponding {@link ObjectPool#put(Object)}.
*
* @param poolableObject controls the lifecycle of the pooled objects.
* @param queue the blocking queue implementation to use
* @param <T> the type of object used in the pool
*
* @return a blocking pool using the default ArrayBlockingQueue implementation of a specific size
*/
public static <T> ObjectPool<T> Blocking(PoolableObject<T> poolableObject, BlockingQueue<T> queue) {
return new BlockingPool<T>(poolableObject, queue);
}
/**
* Creates a non-blocking pool which will grow as much as needed. If the pool is empty, new objects will be created. The items in the
* pool will never expire (see {@link #NonBlockingSoftReference(PoolableObject)} for pooled objects that will expire as needed).
*
* @param poolableObject controls the lifecycle of the pooled objects.
* @param <T> the type of object used in the pool
*
* @return a blocking pool using the default ConcurrentLinkedQueue implementation
*/
public static <T> ObjectPool<T> NonBlocking(PoolableObject<T> poolableObject) {
return new NonBlockingPool<T>(poolableObject);
}
/**
* Creates a non-blocking pool which will grow as much as needed. If the pool is empty, new objects will be created. The items in the
* pool will never expire (see {@link #NonBlockingSoftReference(PoolableObject)} for pooled objects that will expire as needed).
*
* @param poolableObject controls the lifecycle of the pooled objects.
* @param queue the queue implementation to use
* @param <T> the type of object used in the pool
*
* @return a blocking pool using the default ConcurrentLinkedQueue implementation
*/
public static <T> ObjectPool<T> NonBlocking(PoolableObject<T> poolableObject, Queue<T> queue) {
return new NonBlockingPool<T>(poolableObject, queue);
}
/**
* Creates a non-blocking pool which will grow as much as needed. If the pool is empty, new objects will be created. The items in the
* pool will expire in response to memory demand. (See {@link #NonBlocking(PoolableObject)} for pooled objects that will never expire)
*
* @param poolableObject controls the lifecycle of the pooled objects.
* @param <T> the type of object used in the pool
*
* @return a blocking pool using the default ConcurrentLinkedQueue implementation
*/
public static <T> ObjectPool<T> NonBlockingSoftReference(PoolableObject<T> poolableObject) {
return new NonBlockingSoftPool<T>(poolableObject);
}
/**
* Creates a non-blocking pool which will grow as much as needed. If the pool is empty, new objects will be created. The items in the
* pool will expire in response to memory demand. (See {@link #NonBlocking(PoolableObject)} for pooled objects that will never expire)
*
* @param poolableObject controls the lifecycle of the pooled objects.
* @param queue the queue implementation to use
* @param <T> the type of object used in the pool
*
* @return a blocking pool using the default ConcurrentLinkedQueue implementation
*/
public static <T> ObjectPool<T> NonBlockingSoftReference(PoolableObject<T> poolableObject, Queue<SoftReference<T>> queue) {
return new NonBlockingSoftPool<T>(poolableObject, queue);
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright 2014 dorkbox, llc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dorkbox.objectPool;
/**
* @author dorkbox, llc
*/
interface Pool<T> {
/**
* Takes an object from the pool, Blocks until an item is available in the pool.
* <p/>
* This method catches {@link InterruptedException} and discards it silently.
*/
T take();
/**
* Takes an object from the pool, Blocks until an item is available in the pool.
*/
T takeInterruptibly() throws InterruptedException;
/**
* Return object to the pool, waking the threads that have blocked during take()
*/
void put(T object);
/**
* @return a new object instance created by the pool.
*/
T newInstance();
}