All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.e6tech.elements.common.util.concurrent.ObjectPool Maven / Gradle / Ivy

There is a newer version: 2.7.9
Show newest version
/*
 * Copyright 2015-2020 Futeh Kao
 *
 * 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 net.e6tech.elements.common.util.concurrent;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * Usages: 
*

* new ObjectPool<>().type(type).build();
* new ObjectPool<>().factory(factory).build();
* or new ObjectPool<type>(){}.build(); *

*/ public class ObjectPool { private ConcurrentLinkedDeque> deque = new ConcurrentLinkedDeque<>(); private ConcurrentLinkedDeque> entries = new ConcurrentLinkedDeque<>(); private ObjectFactory factory; private Class type; private int limit = 50; private int idleTimeout = 20000; private long lastCleanup = 0L; public ObjectPool build() { if (type == null && factory == null) { Type superClass = getClass().getGenericSuperclass(); if (superClass instanceof Class) { // sanity check, should never happen throw new IllegalArgumentException("Internal error: ObjectPool type information. " + "Try new ObjectPool<>().type(type).build(), " + "new ObjectPool<>().factory(factory).build() " + "or new ObjectPool().build()"); } if (superClass instanceof ParameterizedType) { // sanity check, should never happen Type[] types = ((ParameterizedType) superClass).getActualTypeArguments(); if (types[0] instanceof Class) { type = (Class) types[0]; } else if (types[0] instanceof ParameterizedType && ((ParameterizedType) types[0]).getRawType() instanceof Class) { type = (Class) ((ParameterizedType) types[0]).getRawType(); } } } return this; } public ObjectFactory getFactory() { return factory; } public void setFactory(ObjectFactory factory) { this.factory = factory; } public ObjectPool factory(ObjectFactory factory) { setFactory(factory); return this; } public Class getType() { return type; } public void setType(Class type) { this.type = type; } public ObjectPool type(Class type) { setType(type); return this; } public int getLimit() { return limit; } public void setLimit(int limit) { this.limit = limit; } public ObjectPool limit(int limit) { setLimit(limit); return this; } public int getIdleTimeout() { return idleTimeout; } public void setIdleTimeout(int idleTimeout) { this.idleTimeout = idleTimeout; } public ObjectPool idleTimeout(int idleTimeout) { setIdleTimeout(idleTimeout); return this; } public int size() { return deque.size(); } public ObjectPool clear() { deque.clear(); entries.clear(); return this; } @SuppressWarnings("unchecked") public T create() { if (factory != null) return factory.create(); if (type != null) { try { return (T) type.getDeclaredConstructor().newInstance(); } catch (Exception e) { throw new IllegalArgumentException(e); } } throw new IllegalArgumentException("Internal error: ObjectPool constructed without actual type information"); } public void accept(Consumer consumer) { T t = null; try { t = checkOut(); consumer.accept(t); } finally { if (t != null) checkIn(t); } } public R apply(Function function) { T t = null; try { t = checkOut(); return function.apply(t); } finally { if (t != null) checkIn(t); } } public T checkOut() { if (deque.isEmpty()) { lastCleanup = System.currentTimeMillis(); return create(); } try { Entry entry = deque.removeLast(); T value = entry.value; entry.value = null; if (entries.size() < limit) entries.offer(entry); return value; } catch (NoSuchElementException e) { return create(); } } public void checkIn(T t) { if (t == null) return; if (deque.size() < limit) { Entry entry; try { entry = entries.remove(); } catch (NoSuchElementException e) { entry = new Entry<>(); } entry.value = t; entry.lastAccess = System.currentTimeMillis(); deque.offerLast(entry); } cleanup(); } public void cleanup() { long time = System.currentTimeMillis(); if (time - lastCleanup > idleTimeout) { lastCleanup = time; final Iterator> each = deque.iterator(); while (each.hasNext()) { Entry entry = each.next(); if (time - entry.lastAccess > idleTimeout) { each.remove(); } else { break; } } } } @FunctionalInterface public interface ObjectFactory { T create(); } private static class Entry { long lastAccess; T value; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy