Java最佳实践–多线程环境中的DateFormat

这是有关使用Java编程语言时的拟议实践的系列文章的第一篇。

所有讨论的主题均基于用例,这些用例来自于电信行业的关键任务超高性能生产系统的开发。

在阅读本文的每个部分之前,强烈建议您参考相关的Java API文档以获取详细信息和代码示例。

所有测试均针对具有以下特征的Sony Vaio进行:

  • 系统:openSUSE 11.1(x86_64)
  • 处理器(CPU):Intel(R)Core(TM)2 Duo CPU T6670 @ 2.20GHz
  • 处理器速度:1,200.00 MHz
  • 总内存(RAM):2.8 GB
  • Java:OpenJDK 1.6.0_0 64位

应用以下测试配置:

  • 并发工作者线程:200
  • 每个工作人员重复测试的次数:1000
  • 整体测试次数:100

在多线程环境中使用DateFormat

在多线程环境中使用DateFormat可能很棘手。 Java API文档明确指出:

日期格式不同步。 建议为每个线程创建单独的格式实例。 如果多个线程同时访问一种格式,则必须在外部进行同步。

典型的情况是使用预定义格式将日期转换为字符串表示形式,反之亦然。 为每次转换创建新的DateFormat实例效率很低。 您应该记住,静态工厂方法“ getDateInstance(..)”在使用时也会创建新的DateFormat实例。 大多数开发人员所做的就是使用DateFormat实现类(例如SimpleDateFormat )构造DateFormat实例,并将其值分配给类变量。 类范围的变量用于其所有日期解析和格式设置需求。 前面提到的方法虽然非常有效,但是由于DateFormat类上缺少同步,因此当多个线程访问类变量的相同实例时会引起问题。 解析创建Date对象时抛出的典型异常是:

  • java.lang.NumberFormatException
  • java.lang.ArrayIndexOutOfBoundsException

执行格式化时,您还应该遇到格式错误的“ 日期到字符串”表示形式。

为了正确处理上述问题,弄清多线程环境的体系结构至关重要。 Java虚拟机允许应用程序具有多个并发运行的执行线程。 通常,在多线程环境(JVM内的容器或JVM本身)中,应执行线程池。 工作线程应在启动时构造并初始化,以用于执行程序。 例如,一个Web容器构造了一个工作线程池来服务所有传入的流量。 线程池是处理系统资源的最有效方法,主要是因为线程创建和初始化对于Java虚拟机来说是一项非常耗资源的任务。 不过,只需为要同时执行的每段代码创建一个新的执行线程 ,即可实现应用程序并行性。

关于类范围的DateFormat实例:

  • 如果你已经明确了NO 线程池将在您的环境中使用,那么只有新的主题实例同时访问你的DateFormat实例。 在这种情况下,建议从外部同步该DateFormat实例
  • 如果使用线程池,则可以同时访问DateFormat实例的线程实例数量有限。 因此,建议使用ThreadLocal方法为每个线程创建单独的DateFormat实例。

以下是“ getDateInstance(..)”,“同步”和ThreadLocal方法的示例:

package com.javacodegeeks.test;import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;public class ConcurrentDateFormatAccess {public Date convertStringToDate(String dateString) throws ParseException {return SimpleDateFormat.getDateInstance(DateFormat.MEDIUM).parse(dateString);}}
package com.javacodegeeks.test;import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;public class ConcurrentDateFormatAccess {private DateFormat df = new SimpleDateFormat("yyyy MM dd");public Date convertStringToDate(String dateString) throws ParseException {Date result;synchronized(df) {result = df.parse(dateString);}return result;}}

这里要注意的事情:

  • 每个执行“ convertStringToDate”操作的线程都试图在获取对DateFormat类变量instance的引用之前获取DateFormat对象的监视器锁定。 如果另一个线程持有该锁,则当前线程将等待直到释放该锁。 这样,一次只有一个线程正在访问DateFormat实例。
    package com.javacodegeeks.test;import java.text.DateFormat;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;public class ConcurrentDateFormatAccess {private ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat> () {@Overridepublic DateFormat get() {return super.get();}@Overrideprotected DateFormat initialValue() {return new SimpleDateFormat("yyyy MM dd");}@Overridepublic void remove() {super.remove();}@Overridepublic void set(DateFormat value) {super.set(value);}};public Date convertStringToDate(String dateString) throws ParseException {return df.get().parse(dateString);}}

    这里要注意的事情:

    • 每个执行“ convertStringToDate”操作的线程都将调用“ df.get()”操作,以初始化或检索其本地范围内的DateFormat实例的已初始化引用。

    下面,我们给出上述三种方法之间的性能比较表(注意,我们已经测试了DateFormat实用工具类的解析功能。根据特定的日期格式,我们将日期的String表示形式转换为等效的Date对象)。

    横轴表示测试运行的次数,纵轴表示每次测试运行的每秒平均事务数(TPS)。 因此,较高的值更好。 如您所见,通过使用线程池和ThreadLocal方法,与“同步”方法和“ getDateInstance(..)”方法相比,您可以获得更高的性能。

    最后,我要指出的是,使用不带线程池的ThreadLocal方法等同于使用“ getDateInstance(..)”方法,因为每个新线程都必须在使用之前初始化其本地DateFormat实例,因此需要一个新的DateFormat实例将在每次执行时创建。

    编码愉快!

    贾斯汀

    相关文章 :
    • Java最佳实践–高性能序列化
    • Java最佳实践– Vector vs ArrayList vs HashSet
    • Java最佳实践–字符串性能和精确字符串匹配
    • Java最佳实践–队列之战和链接的ConcurrentHashMap
    • Java最佳实践– Char到Byte和Byte到Char的转换

    翻译自: https://www.javacodegeeks.com/2010/07/java-best-practices-dateformat-in.html

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/374719.shtml

    如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

    相关文章

    IntentDemo

    Intent通信示例&#xff1a; 两个Button&#xff0c;一个startBrowser, 一个startPhone. 其中&#xff0c;OnClickListener()是类View的一个interface&#xff0c;需要实现其中的onClick()函数。 startActivity()开启另一个Activity&#xff0c;本示例中开启Browser或Phone. In…

    androidstudio新建项目中在布局文件中不显示title的方法

    在androidstudio新建项目的时候&#xff0c;在布局文件里有时候会出现如下情况&#xff1a; 上面的标题栏非常碍眼&#xff0c;要想隐藏标题栏的话&#xff0c;可以在Manifest文件的theme标签里进行配置&#xff0c;自定义一个theme&#xff0c;加上如下两句。或者直接在当前th…

    力扣 数组中的第K个最大元素

    给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不是第 k 个不同的元素。 分析&#xff1a;这是个排序题&#xff0c;只要排好序&#xff0c;一切迎刃而解。我决定把排序…

    Xcode插件

    古人云“工欲善其事必先利其器”&#xff0c;打造一个强大的开发环境&#xff0c;是立即提升自身战斗力的绝佳途径&#xff01;以下是搜集的一些有力的XCode插件。1.全能搜索家CodePilot 2.0你要找的是文件&#xff1f;是文件夹&#xff1f;是代码&#xff1f;Never Mind&#…

    JBoss Portal上的“ Hello World” portlet

    Portlet概述 本教程将向您展示如何创建和部署简单的Portlet。 Portlet是基于Java技术的Web组件&#xff0c;可以处理请求并生成动态内容。 Portlet不是自治实体&#xff0c;但是由Portlet容器管理&#xff0c;Portlet容器为Portlet执行提供了必要的运行时环境。 应当注意&…

    Jenkins + GitHub + fir-cli 一行命令从源码到fir.im

    上周简书作者宣X_x 分享了一篇文章——用JenkinsGitHubXcodefir搭了一个持续集成环境&#xff0c;整个记录见(传送门)。 _______ 其实fir.im为我们提供了一个更简单的方式&#xff1a;fir-cli&#xff0c;我们只需要一条命令&#xff0c;就可以从源代码到fir.im。不需要Jenkin…

    Java Persistence API:快速入门

    各位读者好&#xff01; 在我的一些朋友提出无数请求之后&#xff0c;我决定写一篇关于Java Persistence API的简短文章。 面向对象的编程范式是当​​今最流行和使用最广泛的模型&#xff0c;它具有无缝建模现实生活实体的能力&#xff0c;因此它胜过大多数其他范式。 但是&am…

    线性回归、梯度下降(Linear Regression、Gradient Descent)

    转载请注明出自BYRans博客&#xff1a;http://www.cnblogs.com/BYRans/ 实例 首先举个例子&#xff0c;假设我们有一个二手房交易记录的数据集&#xff0c;已知房屋面积、卧室数量和房屋的交易价格&#xff0c;如下表&#xff1a; 假如有一个房子要卖&#xff0c;我们希望通过上…

    使用Oracle WebLogic对应用程序外部的EJB的引用

    在之前的文章中&#xff0c;我们对EJB v。3.0及其为您提供的用于构建Java EE应用程序的可移植机制进行了概述。 由于Java EE规范都是关于可移植性的&#xff0c;因此冒着重复自己的风险&#xff0c;我们经常强调EJB v。3.0规范上仍然存在最重要的可移植性限制&#xff1a;没有在…

    基于verilog的分频器设计(奇偶分频原理及其电路实现:上)

    在一个数字系统中往往需要多种频率的时钟脉冲作为驱动源&#xff0c;这样就需要对FPGA的系统时钟&#xff08;频率太高&#xff09;进行分频。分频器主要分为奇数分频&#xff0c;偶数分频&#xff0c;半整数分频和小数分频&#xff0c;在对时钟要求不是很严格的FPGA系统中&…

    Java判断布尔类型是否相等

    public class Solution{public static void main(String args[]){boolean x1 true;boolean x2 false;boolean x3 true;if(x1!x2){System.out.println("布尔类型变量判断是否相等可以用!");}if(x1x3){System.out.println("布尔类型变量判断是否相等可以用&quo…

    Java_Web三大框架之Hibernate操作数据库(三)

    使用Hibernate操作数据库需要七个步骤&#xff1a;&#xff08;1&#xff09;读取并解析配置文件Configuration conf newConfiguration().configure(); &#xff08;2&#xff09;读取并解析映射信息&#xff0c;创建SessionFactorySessionFactory sf conf.buildSessionFacto…

    Spring MVC开发–快速教程

    这是我们的JCG合作伙伴之一&#xff0c;来自Manoj的有关使用Spring开发Web应用程序的简短教程&#xff0c; 网址为“ The Khangaonkar Report ”。 &#xff08;注意&#xff1a;对原始帖子进行了少量编辑以提高可读性&#xff09; Spring MVC使用基于模型视图控制器体系结构&…

    spring mvc controller间跳转 重定向 传参

    url&#xff1a;http://zghbwjl.blog.163.com/blog/static/12033667220137795252845/ 1. 需求背景 需求&#xff1a;spring MVC框架controller间跳转&#xff0c;需重定向。有几种情况&#xff1a;不带参数跳转&#xff0c;带参数拼接url形式跳转&#xff0c;带参数不拼接参…

    寻找数组的中心索引

    给你一个整数数组 nums &#xff0c;请计算数组的 中心下标 。 数组 中心下标 是数组的一个下标&#xff0c;其左侧所有元素相加的和等于右侧所有元素相加的和。 如果中心下标位于数组最左端&#xff0c;那么左侧数之和视为 0 &#xff0c;因为在下标的左侧不存在元素。这一点…

    一个疏忽引发的思考!(strerror)

    前几天写代码因为自己的疏忽导致一遍又一遍的Segmentation fault (core dumped)。该问题是因为strerror&#xff08;errno&#xff09;返回的指针指向非法的内存导致程序打印错误时崩溃。 尝试数次无果&#xff0c;为了进度。简单粗暴的换成了perror(str)。今天忙里偷闲&#x…

    Java最佳实践–字符串性能和精确字符串匹配

    在使用Java编程语言时&#xff0c;我们将继续讨论与建议的实践有关的系列文章&#xff0c;我们将讨论String性能调优。 我们将专注于如何有效地处理字符串创建&#xff0c; 字符串更改和字符串匹配操作。 此外&#xff0c;我们将提供我们自己的用于精确字符串匹配的最常用算法的…

    keil里面填数据

    编译后寄存器和堆栈的内存数据可以直接写进去的。 寄存器&#xff0c;双击就可以&#xff0c;注意里面是十六进制 堆栈&#xff0c;也是十六进制&#xff0c;八位的 00 00 00 00 &#xff0c;但这个是从右到左的&#xff0c;比如0x00000006 应该填 06 00 00 00 把数据取出来 取…

    调试生产服务器– Eclipse和JBoss展示

    您是否编写有错误的代码&#xff1f; 不&#xff0c;当然不。 对于我们其余的确实会编写带有错误的代码的凡人&#xff0c;我想解决一个非常敏感的问题&#xff1a;调试在生产服务器上运行的应用程序。 因此&#xff0c;您的应用程序已准备好进行部署。 单元测试全部成功&…

    力扣151. 翻转字符串里的单词

    给你一个字符串 s &#xff0c;逐个翻转字符串中的所有 单词 。 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。 请你返回一个翻转 s 中单词顺序并用单个空格相连的字符串。 没思路&#xff0c;看到的官方给的&#xff0c;简洁明了&…