当前位置: 首页 > news >正文

如何招聘软件网站开发人员濮阳做网站推广

如何招聘软件网站开发人员,濮阳做网站推广,php做图片交互网站代码,网站建设外包费用转载自 关于SimpleDateFormat时间格式化线程安全问题昨天推送的文章《关于创建和销毁对象》一文中#xff0c;2.1重复利用对象这一小节所举的SimpleDateFormat格式化时间的例子是不合适的#xff0c;因为多线程场景下#xff0c;SimpleDateFormat存在线程安全问题。在此2.1重复利用对象这一小节所举的SimpleDateFormat格式化时间的例子是不合适的因为多线程场景下SimpleDateFormat存在线程安全问题。在此特别感谢利群、Simon、Aaron等几位同学认真指出。想必大家对SimpleDateFormat并不陌生。SimpleDateFormat 是 Java 中一个非常常用的类该类用来对日期字符串进行解析和格式化输出但如果使用不小心会导致非常微妙和难以调试的问题因为 DateFormat 和 SimpleDateFormat 类不都是线程安全的在多线程环境下调用 format() 和 parse() 方法应该使用同步代码来避免问题。下面我们通过一个具体的场景来一步步的深入学习和理解SimpleDateFormat类。 一.引子 首先我们都知道在程序中我们应当尽量少的创建SimpleDateFormat 实例因为创建这么一个实例需要耗费很大的代价。在一个读取数据库数据导出到excel文件的例子当中每次处理一个时间信息的时候就需要创建一个SimpleDateFormat实例对象然后再丢弃这个对象。大量的对象就这样被创建出来占用大量的内存和 jvm空间。代码如下 public class DateUtil {public static String formatDate(Date date){SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd HH:mm:ss);return sdf.format(date);}public static Date parse(String strDate) throws ParseException{SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd HH:mm:ss);return sdf.parse(strDate);}} 你也许会说OK那我就创建一个静态的simpleDateFormat实例然后放到一个DateUtil类如下中在使用时直接使用这个实例进行操作这样问题就解决了。改进后的代码如下 public class DateUtil {private static final SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd HH:mm:ss);public static String formatDate(Date date){return sdf.format(date);}public static Date parse(String strDate) throws ParseException {return sdf.parse(strDate);} } 当然这个方法的确很不错在大部分的时间里面都会工作得很好。但当你在生产环境中使用一段时间之后你就会发现这么一个事实它不是线程安全的。在正常的测试情况之下都没有问题但一旦在生产环境中一定负载情况下时这个问题就出来了。他会出现各种不同的情况比如转化的时间不正确比如报错比如线程被挂死等等。我们看下面的测试用例拿事实说话 public class DateUtilTest {public static class SimpleDateFormatThreadSafeTest extends Thread {Overridepublic void run() {while (true) {try {this.join(2000);} catch (InterruptedException e1) {e1.printStackTrace();}try {System.out.println(this.getName() : DateUtil.parse(2016-09-13 22:00:00));} catch (ParseException e) {e.printStackTrace();}}}}public static void main(String[] args) {for(int i 0; i 3; i){new SimpleDateFormatThreadSafeTest().start();}} } 执行输出如下 Exception in thread Thread-2 Exception in thread Thread-0 java.lang.NumberFormatException: multiple points at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1110) at java.lang.Double.parseDouble(Double.java:540) at java.text.DigitList.getDouble(DigitList.java:168) at java.text.DecimalFormat.parse(DecimalFormat.java:1321) at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1793) at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455) at java.text.DateFormat.parse(DateFormat.java:355) at com.shengfei.test.DateFormat.DateUtil.parse(DateUtil.java:31) at com.shengfei.test.DateFormat.DateUtilTest$SimpleDateFormatThreadSafeTest.run(DateUtilTest.java:32)java.lang.NumberFormatException: multiple points at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1110) at java.lang.Double.parseDouble(Double.java:540) at java.text.DigitList.getDouble(DigitList.java:168) at java.text.DecimalFormat.parse(DecimalFormat.java:1321) at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1793) at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455) at java.text.DateFormat.parse(DateFormat.java:355) at com.shengfei.test.DateFormat.DateUtil.parse(DateUtil.java:31) at com.shengfei.test.DateFormat.DateUtilTest$SimpleDateFormatThreadSafeTest.run(DateUtilTest.java:32)Thread-1:Mon Sep 13 22:00:00 CST 2202Thread-1:Tue Sep 13 22:00:00 CST 2016Thread-1:Tue Sep 13 22:00:00 CST 2016Thread-1:Tue Sep 13 22:00:00 CST 2016说明Thread-2和Thread-0报java.lang.NumberFormatException: multiple points错误直接挂死没起来Thread-1虽然没有挂死但输出的时间是有错误的比如我们输入的时间是2016-09-13 22:00:00 当会输出Mon Sep 13 22:00:00 CST 2202 这样的灵异事件。 二.原因 我们都知道相比于共享一个变量的开销要比每次创建一个新变量要小很多。上面的优化过的静态的SimpleDateFormat版之所在并发情况下回出现各种灵异错误是因为SimpleDateFormat和DateFormat类不是线程安全的。我们之所以忽视线程安全的问题是因为从SimpleDateFormat和DateFormat类提供给我们的接口上来看实在让人看不出它与线程安全有何相干。只是在JDK文档的最下面有如下说明 SynchronizationDate formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally. 翻译一下就是SimpleDateFormat中的日期格式不是同步的。建议为每个线程创建独立的格式实例。如果多个线程同时访问一个格式则它必须保持外部同步。 下面我们通过看JDK源码来看看为什么SimpleDateFormat和DateFormat类不是线程安全的真正原因。 SimpleDateFormat继承了DateFormat,在DateFormat中定义了一个protected属性的 Calendar类的对象calendar。只是因为Calendar类的概念复杂牵扯到时区与本地化等等Jdk的实现中使用了成员变量来传递参数这就造成在多线程的时候会出现错误。 在format方法里有这样一段代码 private StringBuffer format(Date date, StringBuffer toAppendTo,FieldDelegate delegate) {// Convert input date to time field listcalendar.setTime(date);boolean useDateFormatSymbols useDateFormatSymbols();for (int i 0; i compiledPattern.length; ) {int tag compiledPattern[i] 8;int count compiledPattern[i] 0xff;if (count 255) {count compiledPattern[i] 16;count | compiledPattern[i];}switch (tag) {case TAG_QUOTE_ASCII_CHAR:toAppendTo.append((char)count);break;case TAG_QUOTE_CHARS:toAppendTo.append(compiledPattern, i, count);i count;break;default:subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);break;}}return toAppendTo; }calendar.setTime(date)这条语句改变了calendar稍后calendar还会用到在subFormat方法里而这就是引发问题的根源。想象一下在一个多线程环境下有两个线程持有了同一个SimpleDateFormat的实例分别调用format方法 线程1调用format方法改变了calendar这个字段。 中断来了。 线程2开始执行它也改变了calendar。 又中断了。 线程1回来了此时calendar已然不是它所设的值而是走上了线程2设计的道路。如果多个线程同时争抢calendar对象则会出现各种问题时间不对线程挂死等等。 分析一下format的实现我们不难发现用到成员变量calendar唯一的好处就是在调用subFormat时少了一个参数却带来了这许多的问题。其实只要在这里用一个局部变量一路传递下去所有问题都将迎刃而解。 这个问题背后隐藏着一个更为重要的问题--无状态无状态方法的好处之一就是它在各种环境下都可以安全的调用。衡量一个方法是否是有状态的就看它是否改动了其它的东西比如全局变量比如实例的字段。format方法在运行过程中改动了SimpleDateFormat的calendar字段所以它是有状态的。 这也同时提醒我们在开发和设计系统的时候注意下一下三点: 1.自己写公用类的时候要对多线程调用情况下的后果在注释里进行明确说明 2.对线程环境下对每一个共享的可变变量都要注意其线程安全性 3.我们的类和方法在做设计的时候要尽量设计成无状态的。 三.解决办法 1.需要的时候创建新实例 public class DateUtil {public static String formatDate(Date date){SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd HH:mm:ss);return sdf.format(date);}public static Date parse(String strDate) throws ParseException {SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd HH:mm:ss);return sdf.parse(strDate);} } 说明在需要用到SimpleDateFormat 的地方新建一个实例不管什么时候将有线程安全问题的对象由共享变为局部私有都能避免多线程问题不过也加重了创建对象的负担。在一般情况下这样其实对性能影响比不是很明显的。 2.使用同步同步SimpleDateFormat对象 public class DateUtil {private static SimpleDateFormat sdf2 new SimpleDateFormat(yyyy-MM-dd HH:mm:ss);public static String formatDate2(Date date){synchronized(sdf2){return sdf2.format(date);}}public static Date parse2(String strDate) throws ParseException{synchronized(sdf2){return sdf2.parse(strDate);}} } 说明当线程较多时当一个线程调用该方法时其他想要调用此方法的线程就要block多线程并发量大的时候会对性能有一定的影响。 3.使用ThreadLocal public class ConcurrentDateUtil {private static ThreadLocalDateFormat threadLocal new ThreadLocalDateFormat() {Overrideprotected DateFormat initialValue() {return new SimpleDateFormat(yyyy-MM-dd HH:mm:ss);}};public static Date parse(String dateStr) throws ParseException {return threadLocal.get().parse(dateStr);}public static String format(Date date) {return threadLocal.get().format(date);} } 另外一种写法 public class ThreadLocalDateUtil {private static final String date_format yyyy-MM-dd HH:mm:ss;private static ThreadLocalDateFormat threadLocal new ThreadLocalDateFormat();public static DateFormat getDateFormat(){DateFormat df threadLocal.get();if(dfnull){df new SimpleDateFormat(date_format);threadLocal.set(df);}return df;}public static String formatDate(Date date){return getDateFormat().format(date);}public static Date parse(String strDate) throws ParseException {return getDateFormat().parse(strDate);}} 说明使用ThreadLocal, 也是将共享变量变为独享线程独享肯定能比方法独享在并发环境中能减少不少创建对象的开销。如果对性能要求比较高的情况下一般推荐使用这种方法。 4.抛弃JDK使用其他类库中的时间格式化类 1使用Apache commons 里的FastDateFormat宣称是既快又线程安全的SimpleDateFormat, 可惜它只能对日期进行format, 不能对日期串进行解析。 2使用Joda-Time类库来处理时间相关问题。 做一个简单的压力测试方法1最慢方法3最快但是就算是最慢的方法一性能也不差一般系统方法1和方法2就可以满足所以说在这个点很难成为你系统的瓶颈所在。从简单的角度来说建议使用方法1或者方法2如果在必要的时候追求那么一点性能提升的话可以考虑用方法3用ThreadLocal做缓存。 Joda-Time类库对时间处理方式比较完美建议使用。 参考资料 1.http://dreamhead.blogbus.com/logs/215637834.html 2.http://www.blogjava.net/killme2008/archive/2011/07/10/354062.html
http://www.ihoyoo.com/news/43057.html

相关文章:

  • 手机在线做ppt的网站企业邮箱怎么申请注册流程
  • dedecms生成xml网站地图杭州网站建设seo优化营销制作
  • 青海seo技术培训长沙优化科技有限公司地址
  • 网站建设话语wordpress网站制作app
  • 厦门建设网站的公司江苏网站建设联系方式
  • 360上做网站互联网平台搭建
  • 德德模板网站建设步骤wordpress配置文件在哪
  • 酒泉网站建设优化上海发布首页
  • 像优酷平台网站是怎么做的小程序商城哪的服务好
  • 什么作为国内的主要门户网站三合一网站开发教程
  • 网站自然排名怎么哈尔滨市建设工程信息
  • 网站二级栏目示范建设验收网站
  • 网站建设公司对比网站着陆页是什么意思
  • 移动网站的建设查询域名是否被注册
  • 贵州建设厅考试网站二建成绩新品发布会策划流程
  • 网站开发公司的logapp开发软件财务预测
  • 大朗网站仿做软件工程学科评估
  • 有关建筑网站建设方案案例做一些网站的弹出页面
  • 通过ip访问网站需要怎么做网站开发 卓优科技
  • 网站备案报道哪个网站可以做logo
  • 滁州建设网站临沂网站搜索排名
  • 婚恋网站女孩子做美容wordpress 手动安装插件
  • 长春cms建站网站设计云匠网
  • 上海免费网站建站模板企业网站打不开什么原因
  • asp.net网站开发期末复习题dns 解析错误 网站
  • 仙桃企业网站建设网络营销与直播电商好就业吗
  • 女人被做网站企业网络建设公司排名
  • 郑州做网站哪里便宜洞头网站建设
  • c语言也能干大事网站开发wordpress手机网站模版
  • cms网站开发php网站建设丿金手指花总9