package common;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public abstract class AbstractObjectPool<K, V> {
private Map<K, Instance<V>> pool;
private volatile int maxSize;
public static final int DEFAULT_MAX_SIZE = 0xff;
public AbstractObjectPool(int maxSize) {
this.maxSize = maxSize;
this.pool = new ConcurrentHashMap<K, Instance<V>>();
}
public AbstractObjectPool() {
this.maxSize = DEFAULT_MAX_SIZE;
this.pool = new ConcurrentHashMap<K, Instance<V>>();
}
private static final class Instance<V> {
private volatile int weight;
private final V value;
public Instance(V value) {
if (value == null)
throw new NullPointerException();
this.weight = 1;
this.value = value;
}
public int getWeight() {
return weight;
}
public V getValue() {
return value;
}
public synchronized void addWeight() {
if (weight < Integer.MAX_VALUE)
weight++;
}
}
private void flushPool() {
// pool.clear();
int median = getMedian();
for (Map.Entry<K, Instance<V>> entry : pool.entrySet()) {
if (entry.getValue().getWeight() < median)
pool.remove(entry.getKey());
}
if (pool.size() > maxSize * 0.75 && maxSize < (Integer.MAX_VALUE >> 1))
synchronized (this) {
maxSize <<= 1;
}
}
private int getMedian() {
int[] weights = new int[pool.size()];
int i = 0;
for (Map.Entry<K, Instance<V>> entry : pool.entrySet()) {
weights[i++] = entry.getValue().getWeight();
}
Arrays.sort(weights);
return weights[weights.length / 2];
}
private void addInstance(K key, V value) {
Instance<V> instance = new Instance<V>(value);
pool.put(key, instance);
}
public final V getInstance(K key) {
Instance<V> instance = pool.get(key);
if (instance != null) {
instance.addWeight();
return instance.getValue();
}
if (pool.size() + 1 > maxSize)
flushPool();
V instanceValue = newInstance(key);
addInstance(key, instanceValue);
return instanceValue;
}
public abstract V newInstance(K key);
@Override
public String toString() {
return pool.toString();
}
}
测试类:
package test;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.junit.Test;
import com.bankwel.portal.common.util.AbstractObjectPool;
public class DateFormatTest {
private static AbstractObjectPool<String, SimpleDateFormat> formatPool = new AbstractObjectPool<String, SimpleDateFormat>() {
@Override
public SimpleDateFormat newInstance(String key) {
return new SimpleDateFormat(key);
}
};
private SimpleDateFormat _getFormat(String key) {
return formatPool.getInstance(key);
}
private static final Random RANDOM = new Random();
private static final String[] SPLITORS = { "/", ",", "-", ".", " ", ":", ";", "|", "*" };
private static String getRandomPattern() {
return new StringBuilder().append("yyyy").append(getRandomSplitor()).append("MM").append(getRandomSplitor())
.append("dd").toString();
}
private static String getRandomSplitor() {
return SPLITORS[RANDOM.nextInt(SPLITORS.length)];
}
private static final Date NOW = new Date();
private static Date getRandomDate() {
return NOW;
}
@Test
public void testLocal() {
for (int i = 0; i < 10000; i++)
_getFormat(getRandomPattern()).format(getRandomDate());
}
@Test
public void testApache() {
for (int i = 0; i < 10000; i++)
DateFormatUtils.format(getRandomDate(), getRandomPattern());
}
@Test
public void testJdk() {
for (int i = 0; i < 10000; i++) {
SimpleDateFormat format = new SimpleDateFormat(getRandomPattern());
format.format(getRandomDate());
}
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++)
System.out.println(getRandomSplitor());
}
}
测试结果: