您的位置:首页 > 其它

SimpleDateFormat结合对象池化工具commons-pool

2017-12-10 13:09 477 查看
  关于对象池的概念这里不做过多解释,除了用来缓存数据库连接java.sql.Connection这种重量级对象也适用于其他场景。

  以SimpleDateFormat 为例,这是 Java 中非常常用的一个类,用于解析和格式化日期字符串。

  但是 SimpleDateFormat 在多线程环境中并不是线程安全的。详见这位仁兄的 SimpleDateFormat 的线程安全问题与 ThreadLocal

  实现线程安全的一种思路是用ThreadLocal进行安全变量的副本。

static ThreadLocal<SimpleDateFormat> format1 = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};

public String formatDate(Date date) {
return format1.get().format(date);
}


  但是维持变量副本的资源也是需要消耗资源的。尽管ThreadLocal提供了remove方法以便在请求结束后释放副本,但若在请求结束的时候崩溃副本没有得到释放,将会给内存造成极大的压力。为了应对这种情况我们可以采用jdbc连接池的思想,把对象放入对象池工具里面,用”pool”来约束对象的创建与销毁。

  首先引入Apache commons-pool依赖

<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>1.6</version>
</dependency>


接口的声明

//接口
import java.util.Date;
public interface FormattingService {
String format(Date date);
void setPattern(String pattern);
}


实现类

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool;

public class PooledFormattingService implements FormattingService {

// 对象池的实现
GenericObjectPool<SimpleDateFormat> dateFormatsPool;

private static AtomicInteger count = new AtomicInteger(0);

String pattern;

public PooledFormattingService() {
// 对象池工厂
PoolableObjectFactory factory = new Bas
a828
ePoolableObjectFactory() {
@Override
public Object makeObject() throws Exception {
System.out.println("创建新对象"+(count.incrementAndGet()));
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
};

dateFormatsPool = new GenericObjectPool(factory);
// 这里设置创建新对象的最大数目
dateFormatsPool.setMaxActive(10);
}

public String format(Date date) {
try {
SimpleDateFormat dateFormat =  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);
}

}


测试

import java.util.Date;

public class Mytest {

public static void main(String[] args) {
PooledFormattingService pooledFormattingService = new PooledFormattingService();
//创建20个线程去调用SimpleDateFormat
//由于对象池为10,SimpleDateFormat最多创建10个
for (int i = 0; i < 20; i++) {
new Thread(() -> {
pooledFormattingService.format(new Date());
}).start();

}
}
}


核心实现都在 org.apache.commons.pool.impl.GenericObjectPool里面

这里只展示几个关键参数

maxActive: 链接池中最大连接数,默认为8.
maxIdle: 链接池中最大空闲的连接数,默认为8.
minIdle: 连接池中最少空闲的连接数,默认为0.
maxWait: 当连接池资源耗尽时,调用者最大阻塞的时间,超时将抛异常。默认永不超时.
minEvictableIdleTimeMillis: 连接空闲的最小时间,达到此值后空闲连接将可能会被移除。
softMinEvictableIdleTimeMillis: 连接空闲的最小时间,达到此值后空闲链接将会被移除
numTestsPerEvictionRun: 对于“空闲链接”检测线程而言,每次检测的链接资源的个数。默认为3.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: