org.jgroups.util.Pool Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including
all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and
JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
package org.jgroups.util;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Supplier;
/**
* Manages a fixed pool of resources (e.g. buffers). Uses the fast try-lock operation to get a resource from the pool,
* or returns a newly created resource. When the returned lock is unlocked, that resource becomes available again
* for consumption
* @author Bela Ban
* @since 3.5
*/
public class Pool {
protected final T[] pool;
protected final Lock[] locks;
protected final Supplier creator;
@SuppressWarnings("unchecked")
public Pool(int capacity, Supplier creator) {
this.creator=creator;
this.pool=(T[])new Object[Util.getNextHigherPowerOfTwo(capacity)];
this.locks=new Lock[pool.length];
for(int i=0; i < locks.length; i++)
locks[i]=new ReentrantLock();
}
public T[] getElements() {return pool;}
public int getNumLocked() {
int retval=0;
for(Lock lock: locks)
if(((ReentrantLock)lock).isLocked())
retval++;
return retval;
}
/**
* Gets the next available resource for which the lock can be acquired and returns it and its associated
* lock, which needs to be released when the caller is done using the resource. If no resource in the pool can be
* locked, returns a newly created resource and a null lock. This means that no lock was acquired and thus
* doesn't need to be released.
* @return An Element with T and a lock (possibly null if newly created)
*/
public Element get() {
// start at a random index, so different threads don't all start at index 0 and compete for the lock
int starting_index=((int)(Math.random() * pool.length)) & (pool.length - 1);
for(int i=0; i < locks.length; i++) {
int index=(starting_index + i) & (pool.length -1);
Lock lock=locks[index];
if(lock.tryLock()) {
if(pool[index] != null)
return new Element<>(pool[index], lock);
return new Element<>(pool[index]=creator.get(), lock);
}
}
return new Element<>(creator.get(), null);
}
public String toString() {
StringBuilder sb=new StringBuilder();
int locked=getNumLocked();
sb.append("capacity=" + pool.length + ", locked=" + locked + ", available=" + (pool.length - locked));
return sb.toString();
}
public static class Element {
protected final T element;
protected final Lock lock;
public Element(T element, Lock lock) {
this.element=element;
this.lock=lock;
}
public T getElement() {return element;}
public Lock getLock() {return lock;}
public String toString() {return element + ", " + lock;}
}
public static void main(String[] args) {
final int length=8;
final Map map=new HashMap<>(length);
for(int i=0; i < 100; i++) {
int index=((int)(Math.random() * length)) & (length - 1);
System.out.println("index = " + index);
Integer count=map.get(index);
if(count == null)
map.put(index, 1);
else
map.put(index, ++count);
}
System.out.println("map = " + map);
}
}