伍佰目录 短网址
  当前位置:海洋目录网 » 站长资讯 » 站长资讯 » 文章详细 订阅RssFeed

Jdk8+ 简单、安全、高效的格式化 Date

来源:本站原创 浏览:117次 时间:2022-10-11
SimpleDateFormat 线程不安全

众所周知 SimpleDateFormat 线程不安全,不少朋友被其坑过。

下面是 stackoverflow 的文章 why-is-javas-simpledateformat-not-thread-safe[1] 中的栗子。
































public class ExampleClass {
   private static final Pattern dateCreateP = Pattern.compile("Дата подачи:\\s*(.+)");    private static final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss dd.MM.yyyy");
   public static void main(String[] args) {        ExecutorService executor = Executors.newFixedThreadPool(100);        while (true) {            executor.submit(new Runnable() {                @Override                public void run() {                    workConcurrently();                }            });        }    }
   public static void workConcurrently() {        Matcher matcher = dateCreateP.matcher("Дата подачи: 19:30:55 03.05.2015");        Timestamp startAdvDate = null;        try {            if (matcher.find()) {                String dateCreate = matcher.group(1);                startAdvDate = new Timestamp(sdf.parse(dateCreate).getTime());            }        } catch (Throwable th) {            th.printStackTrace();        }        System.out.print("OK ");    }}

And result :

















OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK OK java.lang.NumberFormatException: For input string: ".201519E.2015192E2"at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)at java.lang.Double.parseDouble(Double.java:538)at java.text.DigitList.getDouble(DigitList.java:169)at java.text.DecimalFormat.parse(DecimalFormat.java:2056)at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1869)at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)at java.text.DateFormat.parse(DateFormat.java:364)at com.nonscalper.webscraper.processor.av.ExampleClass.workConcurrently(ExampleClass.java:37)at com.nonscalper.webscraper.processor.av.ExampleClass$1.run(ExampleClass.java:25)at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)at java.util.concurrent.FutureTask.run(FutureTask.java:266)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)at java.lang.Thread.run(Thread.java:745)
解决方案

1.

每次 new (实例化) SimpleDateFormat

2.

利用 ThreadLocal 确保每个线程都可以得到单独的一个 SimpleDateFormat


public class DateUtil { private static final ThreadLocal<SimpleDateFormat> local = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
public static String format(Date date) {     return local.get().format(date); }
public static Date parse(String dateStr) throws ParseException {     return local.get().parse(dateStr); }}
3.

commons-lang3 中的 FastDateFormat






<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>${commons-lang3-version}</version></dependency>


性能比拼

性能咋样,jmh 来一把,源码见:https://github.com/lets-mica/mica-jmh


# JMH version: 1.21# VM version: JDK 1.8.0_221, Java HotSpot(TM) 64-Bit Server VM, 25.221-b11
Benchmark             Mode  Cnt       Score       Error  UnitsnewSimpleDateFormat  thrpt    5  114072.841 ±   989.135  ops/sthreadLocal          thrpt    5  348207.331 ± 46014.175  ops/sfastDateFormat       thrpt    5  434391.553 ±  7799.593  ops/s

结果:fastDateFormat 得分最高。当然你觉得这样就完了?

利用 Instant + DateTimeFormatter

在 mica 1.2.1 中我们利用 Instant 来中转 Date 使用 DateTimeFormatter 格式化。


public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault());
public String format(Date date) {    return DATETIME_FORMATTER.format(date.toInstant());}

注意:DateTimeFormatter 格式化 Instant 需要指定时区。

jdk 8 压测结果


# JMH version: 1.21# VM version: JDK 1.8.0_221, Java HotSpot(TM) 64-Bit Server VM, 25.221-b11
Benchmark         Mode  Cnt       Score      Error  UnitsfastDateFormat   thrpt    5  417338.980  56543.104  ops/stoInstantFormat  thrpt    5  371028.709  72059.917  ops/s
jdk 11 压测结果


# JMH version: 1.21# VM version: JDK 11.0.4, OpenJDK 64-Bit Server VM, 11.0.4+10-b304.69
Benchmark         Mode  Cnt       Score      Error  UnitsfastDateFormat   thrpt    5  384637.138   7402.690  ops/stoInstantFormat  thrpt    5  487482.436  12490.986  ops/s
结论

使用 DateTimeFormatter + Instant 在 java8 下和 commons-lang3 中的 FastDateFormat 已经接近 ,高版本的 jdk 表现突出。如果你在使用高版本的 jdk 或者考虑后期升级到高版本的 JDK,该方式都是一个不错的选择。


  推荐站点

  • At-lib分类目录At-lib分类目录

    At-lib网站分类目录汇集全国所有高质量网站,是中国权威的中文网站分类目录,给站长提供免费网址目录提交收录和推荐最新最全的优秀网站大全是名站导航之家

    www.at-lib.cn
  • 中国链接目录中国链接目录

    中国链接目录简称链接目录,是收录优秀网站和淘宝网店的网站分类目录,为您提供优质的网址导航服务,也是网店进行收录推广,站长免费推广网站、加快百度收录、增加友情链接和网站外链的平台。

    www.cnlink.org
  • 35目录网35目录网

    35目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向35目录推荐、提交优秀网站。

    www.35mulu.com
  • 就要爱网站目录就要爱网站目录

    就要爱网站目录,按主题和类别列出网站。所有提交的网站都经过人工审查,确保质量和无垃圾邮件的结果。

    www.912219.com
  • 伍佰目录伍佰目录

    伍佰网站目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向伍佰目录推荐、提交优秀网站。

    www.wbwb.net