使用pool2编写时间格式枚举辅助类

本文介绍了一种解决SimpleDateFormat线程安全问题的方法,通过使用Apache Commons Pool2库创建SimpleDateFormat对象池,有效避免了多线程环境下日期格式化可能产生的问题。

一个比较纠结的问题,SimpleDateFormat这个类是线程不安全的,在多线程的并发下极其容易出现问题,每次使用的时候都要新建一个对象太消耗资源。这段时间正好在使用REDIS,REDIS底层是使用的pool2来实现的,所以考虑使用pool2对SimpleDateFormat做一个缓存池,代码如下。

package tests.pool2;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;

public enum DateFormatEnum {
    yyyyMMdd("yyyyMMdd"),
    yyyyMMddWithMinus("yyyy-MM-dd"),
    yyyyMMddWithSpace("yyyy MM dd");


    private GenericObjectPool<SimpleDateFormat> pool;

    private DateFormatEnum(final String pattern) {
        this.pool = new GenericObjectPool<SimpleDateFormat>(new BasePooledObjectFactory<SimpleDateFormat>(){
            @Override
            public SimpleDateFormat create() throws Exception {
                return new SimpleDateFormat(pattern);
            }

            @Override
            public PooledObject<SimpleDateFormat> wrap(SimpleDateFormat obj) {
                return new DefaultPooledObject<SimpleDateFormat>(obj);
            }
        });
    }

    public String convert(Date date){
        SimpleDateFormat sdf = null;
        try {
            sdf = pool.borrowObject();
            return sdf.format(date);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if(null != sdf){
                pool.returnObject(sdf);
            }
        }
    }

    public Date convert(String date){
        SimpleDateFormat sdf = null;
        try {
            sdf = pool.borrowObject();
            return sdf.parse(date);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if(null != sdf){
                pool.returnObject(sdf);
            }
        }
    }
}

测试代码如下,没有出现报错了。
oldFashion为错误写法,enumStyle为使用枚举连接池写法。

package tests.pool2;

import java.text.SimpleDateFormat;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.junit.Test;

public class DateTest {

    protected static final int COUNTERS = 100000;

    @Test
    public void oldFashion() throws InterruptedException, ExecutionException, TimeoutException {
        final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        final String pattern = "20160504";

        ExecutorService exec = Executors.newFixedThreadPool(3);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < COUNTERS; i++) {
                    try {
                        String pattern2 = sdf.format(sdf.parse(pattern));
                        if (!pattern.equals(pattern2)) {
                            throw new RuntimeException("oooooooops...." + pattern2);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("======over");
            }
        };
        exec.execute(runnable);
        exec.execute(runnable);
        exec.execute(runnable);
        exec.shutdown();
        exec.awaitTermination(10, TimeUnit.MINUTES);

    }


    @Test
    public void enumStyle() throws InterruptedException {
        final String pattern = "20160504";

        ExecutorService exec = Executors.newFixedThreadPool(10);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < COUNTERS; i++) {
                    String pattern2 = DateFormatEnum.yyyyMMdd.convert(DateFormatEnum.yyyyMMdd.convert(pattern));
                    if (!pattern.equals(pattern2)) {
                        throw new RuntimeException("oooooooops...." + pattern2);
                    }
                }
                System.out.println("======over");
            }
        };
        exec.execute(runnable);
        exec.execute(runnable);
        exec.execute(runnable);
        exec.execute(runnable);
        exec.execute(runnable);
        exec.execute(runnable);
        exec.execute(runnable);
        exec.execute(runnable);
        exec.execute(runnable);
        exec.execute(runnable);
        exec.execute(runnable);
        exec.execute(runnable);
        exec.execute(runnable);
        exec.execute(runnable);
        exec.execute(runnable);
        exec.execute(runnable);
        exec.shutdown();
        exec.awaitTermination(10, TimeUnit.MINUTES);

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值