Updated object pool to have Blocking, Non-Blocking, and Non-Blocking (soft references) pool types
This commit is contained in:
parent
ef5e71d18a
commit
1a9e0bb8ac
|
@ -44,7 +44,7 @@ Usage:
|
|||
<dependency>
|
||||
<groupId>com.dorkbox</groupId>
|
||||
<artifactId>ObjectPool</artifactId>
|
||||
<version>2.1</version>
|
||||
<version>2.2</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue