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

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

  1. 每次都new 一个SimpleDateFormat对象,但频繁的创建与销毁对象带来的性能问题……哈哈,我就不在这里过多的BB了。
  2. 使用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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值