- 浏览: 375398 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
u014689192:
很不错
JMX学习笔记(三)-MXBean -
focus2008:
进制转换之后,根本不会执行js代码,感觉你没有测试过吧
xss漏洞之进制转换 -
focus2008:
如何使用过滤器来处理呢?
xss漏洞之进制转换 -
1169158401:
我艹,我那天这么写,包括一些方法,然后那货说这样写不容易看懂。 ...
import static简化代码 -
AquariusM:
奢华的JVM介绍!
JMX学习笔记(三)-MXBean
以前写过一篇 , 《SimpleDateFormat性能调优》http://tuhaitao.iteye.com/admin/blogs/822277
虽然可以解决SimpleDateFormat的线程安全问题,但不能够灵活的配置日期Parten,为了使其能够灵活的配置日期格式,我进行了一番改造。
1. 通过配置文件加载Praten,灵活配置日期格式
2. 使用FastHashMap结合ThreadLocal,解决多个日期格式的线程安全问题
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.opencfg.core; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import org.apache.commons.collections.FastHashMap; import org.apache.commons.lang.StringUtils; /** * <p> * DateFormat Utils * <p> * * <p>#ThreadSafe#</p> * * @author Opencfg Software Foundation * @since 0.0.1-SNAPSHOT * @version $Id: DateFormatUtils.java 2011-06-14 23:21:53 reymondtu $ */ public class DateFormatUtils { private static final FastHashMap datePartenMap = new FastHashMap(); static { // load data parten properties files List<String> propList = PropertiesUtils.getSimpleList("DateFormatUtils.properties") ; datePartenMap.setFast(true); for(String dateParten : propList) { if(StringUtils.startsWith(dateParten, "#")) continue; datePartenMap.put(StringUtils.trim(dateParten), new SimpleDateFormat(dateParten)); } } /** * String -> Date * * @param dateParten Parse Date Parten * @param dateStr Parse Date String * @throws ParseException */ public static Date safeParseDate(final String dateParten, final String dateStr) throws ParseException { return getFormat(dateParten).parse(dateStr); } /** * Date -> String * * @param dateParten Format Date Parten * @param date Format java.util.Date Object */ public static String safeFormatDate(final String dateParten, final Date date) { return getFormat(dateParten).format(date); } private static ThreadLocal<FastHashMap> threadLocal = new ThreadLocal<FastHashMap>(){ protected synchronized FastHashMap initialValue() { return (FastHashMap)datePartenMap.clone(); } }; private static DateFormat getFormat(final String dateParten){ return (DateFormat)threadLocal.get().get(dateParten); } }
这里使用了apache commons-collections里的FashHashMap类,此类适用于读多写少的高并发操作,很适合写缓存.
下边是读取配置文件的类:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.opencfg.core; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.net.URL; import java.util.ArrayList; import java.util.List; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy; import org.apache.commons.lang.StringUtils; /** * <p> * Properties Utils * <p> * * <p>#ThreadSafe#</p> * * @author Opencfg Software Foundation * @since 0.0.1-SNAPSHOT * @version $Id: PropertiesUtils.java 2011-06-15 01:22:53 reymondtu $ */ public class PropertiesUtils { /** * Load Properties File * @throws ConfigurationException */ public static PropertiesConfiguration loadClassPathProperties(final String fileName, final long refreshInterval) throws ConfigurationException { URL url = PropertiesUtils.class.getClassLoader().getResource(fileName); File f = new File(url.getFile()); if(!f.exists()) { throw new IllegalArgumentException("can not load file " + fileName); } PropertiesConfiguration prop = new PropertiesConfiguration(url.getFile()); FileChangedReloadingStrategy fcrs = null; fcrs = new FileChangedReloadingStrategy(); fcrs.setRefreshDelay(refreshInterval); prop.setReloadingStrategy(fcrs); return prop; } public static List<String> getSimpleList(final String fileName) { try { PropertiesConfiguration prop = loadClassPathProperties(fileName, 500); BufferedReader reader = new BufferedReader(new FileReader(prop.getFile())); List<String> list = new ArrayList<String>(); String line = null; while ((line =reader.readLine())!= null) { if(StringUtils.startsWith(line, "#")) { continue; } list.add(line); line = reader.readLine(); } return list; } catch (Exception e) { throw new IllegalArgumentException("can not load file " + fileName); } } }
配置文件DateFormatUtils.properties如下:
#show all yyyy-MM-dd HH:mm:ss yyyy年MM月dd日 HH:mm:ss yyyy年MM月dd日 HH时mm分ss秒 #only show date yyyy-MM-dd yyyy年MM月dd日 #only show hour,minute,second HH:mm:ss HH时mm分ss秒
这里我跟传统的SimpleDateFormat,apache 的 FastDateForma, DateUtilst做了性能对比:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.opencfg.core; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import org.apache.commons.lang.time.FastDateFormat; import org.junit.Before; import org.junit.Test; /** * DateFormatUtils JUnit4 Test * * @author Opencfg Software Foundation * @since 0.0.1-SNAPSHOT * @version $Id: DateFormatUtilsTest.java 2011-06-15 00:36:53 reymondtu $ */ public class DateFormatUtilsTest { private final int TEST_SIZE = 1000000; private Date[] dateArray = new Date[TEST_SIZE]; private String[] stringArray = new String[TEST_SIZE]; @Before public void setUp() { for(int i = 0; i < TEST_SIZE; i++) { dateArray[i] = new Date(); } for(int i = 0; i < TEST_SIZE; i++) { stringArray[i] = DateFormatUtils.safeFormatDate("yyyy-MM-dd HH:mm:ss", new Date()); } } /* Format */ @Test public void test_JDK_SimpleDateFormat_format() { long starttime = System.currentTimeMillis(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); for(Date date : dateArray) { sdf.format(date); } long endtime = System.currentTimeMillis(); System.out.println("JDK SimpleDateFormat format cost:" + (endtime - starttime) + "ms"); } @Test public void test_Opencfg_DateFormatUtils_format() { long starttime = System.currentTimeMillis(); for(Date date : dateArray) { DateFormatUtils.safeFormatDate("yyyy-MM-dd HH:mm:ss", date); } long endtime = System.currentTimeMillis(); System.out.println("Opencfg DateFormatUtils format cost:" + (endtime - starttime) + "ms"); } @Test public void test_Apache_FastDateFormat_format() { FastDateFormat fastDateFormat = FastDateFormat.getInstance(); long starttime = System.currentTimeMillis(); for(Date date : dateArray) { fastDateFormat.format(date); } long endtime = System.currentTimeMillis(); System.out.println("Apache FastDateFormat format cost:" + (endtime - starttime) + "ms"); } /* Parse */ @Test public void test_JDK_SimpleDateFormat_parse() throws ParseException { long starttime = System.currentTimeMillis(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); for(String str : stringArray) { sdf.parse(str); } long endtime = System.currentTimeMillis(); System.out.println("JDK SimpleDateFormat parse cost:" + (endtime - starttime) + "ms"); } @Test public void test_Opencfg_DateFormatUtils_parse() throws ParseException { long starttime = System.currentTimeMillis(); for(String str : stringArray) { DateFormatUtils.safeParseDate("yyyy-MM-dd HH:mm:ss", str); } long endtime = System.currentTimeMillis(); System.out.println("Opencfg DateFormatUtils parse cost:" + (endtime - starttime) + "ms"); } @Test public void test_Apache_DateUtils_parse() throws ParseException { long starttime = System.currentTimeMillis(); String[] dateParten = new String[]{"yyyy-MM-dd HH:mm:ss"}; for(String str : stringArray) { org.apache.commons.lang.time.DateUtils.parseDate(str, dateParten); } long endtime = System.currentTimeMillis(); System.out.println("Apache DateUtils parse cost:" + (endtime - starttime) + "ms"); } }
这里分别用100W个string数组 与100W个Date数组做了实验,结果如下
JDK SimpleDateFormat format cost:1313ms Opencfg DateFormatUtils format cost:844ms Apache FastDateFormat format cost:1860ms
JDK SimpleDateFormat parse cost:3563ms Opencfg DateFormatUtils parse cost:3641ms Apache DateUtils parse cost:16656ms
在单线程测试中,Opencfg DateFormatUtils的format能力 明显高于JDK 40%、Aapache 50%, parse的能力与单线成下的SimpleDateFormat相当, 与Apache的DateUtils明显不在一个级别,性能高出500%。
下边我使用多线程测试:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.opencfg.core; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import org.apache.commons.lang.time.FastDateFormat; import org.junit.Before; import org.junit.Test; /** * DateFormatUtils JUnit4 Test * * @author Opencfg Software Foundation * @since 0.0.1-SNAPSHOT * @version $Id: DateFormatUtilsMutiThreadTest.java 2011-07-18 23:06:53 reymondtu $ */ public class DateFormatUtilsMutiThreadTest { private final int TEST_SIZE = 1000000; private final int TEST_THREAD_COUNT = 10; private Date[] dateArray = new Date[TEST_SIZE]; private String[] stringArray = new String[TEST_SIZE]; @Before public void setUp() { for(int i = 0; i < TEST_SIZE; i++) { dateArray[i] = new Date(); } for(int i = 0; i < TEST_SIZE; i++) { stringArray[i] = DateFormatUtils.safeFormatDate("yyyy-MM-dd HH:mm:ss", new Date()); } } /* Format */ @Test public void test_Apache_FastDateFormat_format() throws InterruptedException { final FastDateFormat fastDateFormat = FastDateFormat.getInstance(); long starttime = System.currentTimeMillis(); int avr = TEST_SIZE/TEST_THREAD_COUNT; for(int i = 0; i < TEST_THREAD_COUNT; i ++) { final int start = i * avr; final int end = (i + 1) * avr; Thread t = new Thread(new Runnable() { @Override public void run() { for(int j = start; j < end ; j ++) { fastDateFormat.format(dateArray[j]); } } }); t.start(); t.join(); } long endtime = System.currentTimeMillis(); System.out.println("Apache Muti-Thread FastDateFormat format cost:" + (endtime - starttime) + "ms"); } @Test public void test_JDK_SimpleDateFormat_format() throws InterruptedException { long starttime = System.currentTimeMillis(); final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); int avr = TEST_SIZE/TEST_THREAD_COUNT; for(int i = 0; i < TEST_THREAD_COUNT; i ++) { final int start = i * avr; final int end = (i + 1) * avr; Thread t = new Thread(new Runnable() { @Override public void run() { for(int j = start; j < end ; j ++) { sdf.format(dateArray[j]); } } }); t.start(); t.join(); } long endtime = System.currentTimeMillis(); System.out.println("JDK Muti-Thread SimpleDateFormat format cost:" + (endtime - starttime) + "ms"); } @Test public void test_Opencfg_DateFormatUtils_format() throws InterruptedException { long starttime = System.currentTimeMillis(); int avr = TEST_SIZE/TEST_THREAD_COUNT; for(int i = 0; i < TEST_THREAD_COUNT; i ++) { final int start = i * avr; final int end = (i + 1) * avr; Thread t = new Thread(new Runnable() { @Override public void run() { for(int j = start; j < end ; j ++) { DateFormatUtils.safeFormatDate("yyyy-MM-dd HH:mm:ss", dateArray[j]); } } }); t.start(); t.join(); } long endtime = System.currentTimeMillis(); System.out.println("Opencfg Muti-Thread DateFormatUtils format cost:" + (endtime - starttime) + "ms"); } /* Parse */ @Test public void test_Apache_DateUtils_parse() throws ParseException, InterruptedException { long starttime = System.currentTimeMillis(); final String[] dateParten = new String[]{"yyyy-MM-dd HH:mm:ss"}; int avr = TEST_SIZE/TEST_THREAD_COUNT; for(int i = 0; i < TEST_THREAD_COUNT; i ++) { final int start = i * avr; final int end = (i + 1) * avr; Thread t = new Thread(new Runnable() { @Override public void run() { for(int j = start; j < end ; j ++) { try { org.apache.commons.lang.time.DateUtils.parseDate(stringArray[j], dateParten); } catch (ParseException e) { e.printStackTrace(); } } } }); t.start(); t.join(); } long endtime = System.currentTimeMillis(); System.out.println("Apache Muti-Thread DateUtils parse cost:" + (endtime - starttime) + "ms"); } @Test public void test_JDK_SimpleDateFormat_parse() throws ParseException, InterruptedException { long starttime = System.currentTimeMillis(); final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); int avr = TEST_SIZE/TEST_THREAD_COUNT; for(int i = 0; i < TEST_THREAD_COUNT; i ++) { final int start = i * avr; final int end = (i + 1) * avr; Thread t = new Thread(new Runnable() { @Override public void run() { for(int j = start; j < end ; j ++) { try { sdf.parse(stringArray[j]); } catch (ParseException e) { e.printStackTrace(); } } } }); t.start(); t.join(); } long endtime = System.currentTimeMillis(); System.out.println("JDK Muti-Thread SimpleDateFormat parse cost:" + (endtime - starttime) + "ms"); } @Test public void test_Opencfg_DateFormatUtils_parse() throws ParseException, InterruptedException { long starttime = System.currentTimeMillis(); int avr = TEST_SIZE/TEST_THREAD_COUNT; for(int i = 0; i < TEST_THREAD_COUNT; i ++) { final int start = i * avr; final int end = (i + 1) * avr; Thread t = new Thread(new Runnable() { @Override public void run() { for(int j = start; j < end ; j ++) { try { DateFormatUtils.safeParseDate("yyyy-MM-dd HH:mm:ss", stringArray[j]); } catch (ParseException e) { e.printStackTrace(); } } } }); t.start(); t.join(); } long endtime = System.currentTimeMillis(); System.out.println("Opencfg Muti-Thread DateFormatUtils parse cost:" + (endtime - starttime) + "ms"); } }
这里还是使用了100W个String,100W个Date, 每个测试开启10个线程, 测试结果如下:
Apache Muti-Thread FastDateFormat format cost:2265ms JDK Muti-Thread SimpleDateFormat format cost:766ms Opencfg Muti-Thread DateFormatUtils format cost:891ms
Apache Muti-Thread DateUtils parse cost:16766ms JDK Muti-Thread SimpleDateFormat parse cost:3594ms Opencfg Muti-Thread DateFormatUtils parse cost:3860ms
从结果中可以看出Opencfg的DateFormatUtils性能接近与SimpleDateFormat,远远高出Apache的FastDateFormat与DateUtils,同时又提供了基于ThreadLocal的线程安全保障。:)
评论
return (DateFormat)threadLocal.get().get(dateParten);
}
这里threadLocal取出来, 怎么不用close?
你说的是ThreadLocal的remove()吧,貌似木有close()方法,
这里肯定不能remove,因为要缓存,如果remove了,每次都要new SimpleDateFormat,性能很低
return (DateFormat)threadLocal.get().get(dateParten);
}
这里threadLocal取出来, 怎么不用close?
发表评论
-
import static简化代码
2011-11-03 00:10 1631喜欢定义常量的哥们你伤不起啊,好处当然是大大滴,但是定义的名字 ... -
Java永远的伤-中国1927年12月31日午夜
2011-08-15 20:44 3838话说在中国1927年12月31日午 ... -
xss漏洞之进制转换
2011-07-18 01:17 11160SQL注入的事件已经是上个世纪最令人头疼的攻击方法,21世纪又 ... -
tomcat关不掉的原因
2011-07-12 23:51 43407tomcat/bin 目录下的catalina.sh是比较常用 ... -
接口调用频率限制代码
2011-06-28 20:49 10553有很多时候我们写的代码不是你想跑多快就能跑多快的, 因为一些陈 ... -
java调用linux命令传递参数问题
2011-05-18 02:04 10646简单的不带通配符linux命令调用非常简单,使用Runtime ... -
Java位运算的优势
2011-04-09 01:58 2237在Java中对数据的运算,有很好的规范支持,尤其是针对二进制的 ... -
Facebook BigPipe技术
2011-01-04 00:37 2652关于web应用,从html的产生,到客户端浏览器的渲染, ... -
SimpleDateFormat性能调优
2010-11-25 00:12 4145万能的SimpleDateFormat可以把java.util ... -
JMX学习笔记(三)-MXBean
2010-11-10 11:25 4943在MBean中有只要遵循以下两个规则,我们就可以在jc ... -
JMX学习笔记(二)-Notification
2010-11-07 15:25 8936Notification 通知,也可理解为消息,有通知,必 ... -
JMX学习笔记(一)-MBean
2010-10-16 16:27 13598JMX 即 Java Management Ex ... -
cookie安全
2010-07-06 01:09 4112cookie的domian,path,expires, ... -
native2ascii转换后仍然乱码
2010-04-18 17:47 1769native2ascii转换的时候如果不带-encoding ... -
JPA换进下慎用entity
2010-01-26 11:36 2584今天跟一个同事调试代码,突然发现,诸如findUser ... -
http session原理
2009-12-02 00:41 2812大家都知道session是web中在服务器端保存用户状 ... -
java中获得当前目录的各种方法
2009-09-04 11:21 14332Java本来就是跨平台的编程工具,所以当然要做跨平台的 ... -
String、StringBuffer与StringBuilder
2009-04-26 22:04 1876先不废话了,来段程序: package com.tuz; ...
相关推荐
高并发之-SimpleDateFormat类的线程安全问题和解决方案.docx
有关SimpleDateFormat的常用方法说明
JavaScript实现的java.text.SimpleDateFormat。希望多多交流。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); date.setTime(time); System.out.println(sdf.format(date)); 发现时间于想要的时间不符,请运行Time.reg文件
日期操作。。。基础的SimpleDateFormat格式化日期!!操作!》初级学习代码
由浅入深解析 SimpleDateFormat 由浅入深解析 SimpleDateFormat
SimpleDateFormat使用详解。非常实用!!!!
java 使用SimpleDateFormat类获取系统的当前时间 java 使用SimpleDateFormat类获取系统的当前时间
目录SimpleDateFormat诡异bug复现SimpleDateFormat诡异bug字符串日期转Date日期(parse)Date日期转String类型(format)SimpleDateFormat出现bug的原因如何解决SimpleDateFormat多线程安全问题局部变量使用...
深入理解Java:SimpleDateFormat安全的时间格式化
1.创建SimpleDateFormat对象,确定日期被格式化的格式 2.使用循环,在循环中调用Thread的sleep方法,让线程休眠1s后打印当前时间的字符串
NULL 博文链接:https://qinchaoyong.iteye.com/blog/543109
NULL 博文链接:https://chaoyi.iteye.com/blog/2082317
NULL 博文链接:https://flynndang.iteye.com/blog/711878
SimpleDateFormat里面对应格式化输出的模式字母
SimpleDateFormat 是一个以国别敏感的方式格式化和分析数据的具体类。这篇文章主要介绍了Java中的SimpleDateFormat使用详解,需要的朋友可以参考下
主要为大家详细介绍了Java中SimpleDateFormat的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
SimpleDateFormat线程不安全的5种解决方案.md
主要介绍了Java多线程环境下SimpleDateFormat类安全转换,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧