您的位置:首页 > 编程语言 > Java开发

一个简单的Java对象池实现——可用来解决SimpleDateFormat的线程安全问题

2016-06-17 17:55 876 查看
被SimpleDateFormat的线程安全问题困扰过的人应该不止我一个吧。为了解决这个类的线程安全问题,通常我们会有以下两种做法:

每次都new 一个SimpleDateFormat对象,但频繁的创建与销毁对象带来的性能问题……哈哈,我就不在这里过多的BB了。

使用ThreadLocal技术,这恐怕是最常用的一种解决方案,我想几乎每个有经验的Java程序员都使用过它,在此我也不多说啦,如果真有不知到的,且看下面这篇博文:

SimpleDateFormat的线程安全问题与解决方案

然而,最近在调试过程中意外进入了 XStream这个类库, XStream是一个可以将javaBean与XML双向转换的java类库,本文内容基于xstream-1.4.9版本。所需maven依赖如下:

<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.9</version>
</dependency>


不过,本文不是讲解这个类库是如何使用的,而是想说,我在这个类库中发现了一种新颖的可以避免SimpleDateFormat线程安全问题的实现:也即采用对象池,让不同的线程可以使用对象池中不同的SimpleDateFormat对象,并且保证在同一时刻池中的任一对象只能被一条线程使用,从而避免线程安全。

当然XStream中的对象池的实现及其简单,只有简单的借出对象和归还对象,所以完善程度远远无法和apache common pool这种通用且成熟的对象池实现相比(进一个类,数行代码)。不过对于帮助我没理解对象池如何实现到是大有用处。由于实现简单,我就不多解释了,直接贴代码吧。

对象池的简单java实现如下(出自XStream库)

public class Pool {

public interface Factory {
public Object newInstance();
}

private final int initialPoolSize;
private final int maxPoolSize;
private final Factory factory;
private transient Object[] pool;
private transient int nextAvailable;
private transient Object mutex = new Object();

public Pool(int initialPoolSize, int maxPoolSize, Factory factory) {
this.initialPoolSize = initialPoolSize;
this.maxPoolSize = maxPoolSize;
this.factory = factory;
}

public Object fetchFromPool() {
Object result;
synchronized (mutex) {
if (pool == null) {
pool = new Object[maxPoolSize];
for (nextAvailable = initialPoolSize; nextAvailable > 0; ) {
putInPool(factory.newInstance());
}
}
while (nextAvailable == maxPoolSize) {
try {
mutex.wait();
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted whilst waiting " +
"for a free item in the pool : " + e.getMessage());
}
}
result = pool[nextAvailable++];
if (result == null) {
result = factory.newInstance();
putInPool(result);
++nextAvailable;
}
}
return result;
}

protected void putInPool(Object object) {
synchronized (mutex) {
pool[--nextAvailable] = object;
mutex.notify();
}
}

private Object readResolve() {
mutex = new Object();
return this;
}
}


线程安全的SimpleDateFormat的实现如下(同样出自XStream包):

public class ThreadSafeSimpleDateFormat {

private final String formatString;
private final Pool pool;

public ThreadSafeSimpleDateFormat(String format, int initialPoolSize, int maxPoolSize, final boolean lenient) {
formatString = format;
pool = new Pool(initialPoolSize, maxPoolSize, new Pool.Factory() {
public Object newInstance() {
SimpleDateFormat dateFormat = new SimpleDateFormat(formatString, Locale.ENGLISH);
dateFormat.setLenient(lenient);
return dateFormat;
}

});
}

public String format(Date date) {
DateFormat format = fetchFromPool();
try {
return format.format(date);
} finally {
pool.putInPool(format);
}
}

public Date parse(String date) throws ParseException {
DateFormat format = fetchFromPool();
try {
return format.parse(date);
} finally {
pool.putInPool(format);
}
}

private DateFormat fetchFromPool() {
TimeZone tz = TimeZone.getDefault();
DateFormat format = (DateFormat)pool.fetchFromPool();
if (!tz.equals(format.getTimeZone())) {
format.setTimeZone(tz);
}
return format;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线程安全 java