package cyrille.pool;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import junit.framework.TestCase;
import org.apache.commons.lang.time.DurationFormatUtils;
import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool;
public class PoolTest extends TestCase {
public static interface FormattingService {
public String format(Date date);
public void setPattern(String pattern);
}
public static class LockedFormattingService implements FormattingService {
DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
final Lock readLock = readWriteLock.readLock();
final Lock writeLock = readWriteLock.writeLock();
public String format(Date date) {
readLock.lock();
try {
return dateFormat.format(date);
} finally {
readLock.unlock();
}
}
public void setPattern(String pattern) {
writeLock.lock();
try {
this.dateFormat = new SimpleDateFormat(pattern);
} finally {
writeLock.unlock();
}
}
}
public static class PooledFormattingService implements FormattingService {
ObjectPool dateFormatsPool;
String pattern;
public PooledFormattingService() {
PoolableObjectFactory factory = new BasePoolableObjectFactory() {
@Override
public Object makeObject() throws Exception {
return new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
}
};
dateFormatsPool = new GenericObjectPool(factory);
}
public String format(Date date) {
try {
SimpleDateFormat dateFormat = (SimpleDateFormat) this.dateFormatsPool.borrowObject();
try {
return dateFormat.format(date);
} finally {
this.dateFormatsPool.returnObject(dateFormat);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void setPattern(final String pattern) {
PoolableObjectFactory factory = new BasePoolableObjectFactory() {
@Override
public Object makeObject() throws Exception {
return new SimpleDateFormat(pattern);
}
};
this.dateFormatsPool = new GenericObjectPool(factory);
}
}
public static class RecreateFormattingService implements FormattingService {
String pattern = "dd/MM/yyyy HH:mm:ss";
public String format(Date date) {
SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
return dateFormat.format(date);
}
public void setPattern(String pattern) {
this.pattern = pattern;
}
}
public static class SynchronizedFormattingService implements FormattingService {
DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
public synchronized String format(Date date) {
return dateFormat.format(date);
}
public synchronized void setPattern(String pattern) {
this.dateFormat = new SimpleDateFormat(pattern);
}
}
public void test() throws Exception {
test(new RecreateFormattingService());
test(new SynchronizedFormattingService());
test(new PooledFormattingService());
test(new LockedFormattingService());
}
public void test(final FormattingService formattingService) throws Exception {
final int THREADS_COUNT = 50;
ExecutorService executorService = Executors.newFixedThreadPool(THREADS_COUNT);
long startMillis = System.currentTimeMillis();
for (int i = 0; i < THREADS_COUNT; i++) {
Runnable formatDateCommand = new Runnable() {
public void run() {
for (int j = 0; j < 100000; j++) {
formattingService.format(new Date());
// StressTestUtils.incrementProgressBarSuccess();
}
}
};
executorService.execute(formatDateCommand);
}
executorService.shutdown();
while (executorService.isShutdown() == false) {
formattingService.setPattern("dd/MM/yyyy HH:mm:ss");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
long endMillis = System.currentTimeMillis();
System.out.println("Duration for " + formattingService + ": " + DurationFormatUtils.formatDurationHMS(endMillis - startMillis));
}
}