繁体   English   中英

为什么TimeZone.getTimeZone(id)已同步,为什么没有记录?

[英]Why is TimeZone.getTimeZone(id) synchronized, and why this isn't documented?

java.util.TimeZone.getTimeZone(id)是一种基于id获取时区的方法。 当我使用该类时,我用反编译器打开它,发现它是synchronized 由于它是static ,这意味着没有两个线程可以同时调用该方法。 如果多个线程(例如在Web应用程序中)经常获得时区,这可能会非常痛苦。 为什么必须同步?

然后我意识到文档没有说同步。 所以,我的反编译器可能是错误的。 然后我打开了源 ,它是同步的。 为什么没有记录? 我知道javadoc不包含synchronized关键字,但可以提到它。

当然,解决方案是使用joda-time DateTimeZone

该方法最终可以实际创建TimeZone (遵循代码)并将其添加到Map 我猜大家都认为这不是你应该经常打电话的方法,而是采取了简单的方法。

我很难想出一个合法的案例,其中这个synchronized会被争议。 无争议的synchronized (即使在非常高性能的情况下,这是我经常工作的东西)作为芯片便宜。

要获得争用,您不仅需要许多线程,还需要同时触及此特定代码块的许多线程。 如果您在这种情况下遇到问题,可以轻松地将自己的缓存保存在ConcurrentHashMap ,或者保存在完全解锁的结构中。

至于为什么没有记录 - 同步是实现的属性。 欢迎您实现不执行此同步的备用库。 JDK文档记录了Java库,而不是(大部分)Sunacle的实现。

我们看到了同样的问题,在TimeZone中阻塞了线程。 它看起来像2011年11月引入的回归,请参阅http://hg.openjdk.java.net/jdk6/jdk6/jdk/annotate/dd8956e41b89/src/share/classes/java/util/TimeZone.java 以前TimeZone使用了InheritableThreadLocal作为Map。 TimeZone函数现在由SecurityManager控制(在AppContext类下具有同步的HashMap)。 以下函数受到影响:Date.normalize(由toString,getTime和一堆不推荐的方法调用),Calendar.getInstance(Locale是参数的那个除外)。 http://coffeedriven.org/2012/10/14/be-carefull-with-calendar-getinstance-and-timezone-gettimezone也指同一个问题。

VisualVM的堆栈跟踪(JDK6.45):

java.lang.Thread.State: BLOCKED (on object monitor)
at sun.awt.AppContext.get(AppContext.java:572)
- waiting to lock <0x0000000705490070> (a java.util.HashMap)
at sun.awt.AppContext$6.get(AppContext.java:774)
at java.util.TimeZone.getDefaultInAppContext(TimeZone.java:637)
at java.util.TimeZone.getDefaultRef(TimeZone.java:523)
at java.util.Date.normalize(Date.java:1176)
at java.util.Date.toString(Date.java:1010)

我打算在此向Oracle提交错误报告,我只需要重新创建一个小测试用例,以便通过建议的代码修复来清楚地演示问题。

JodaTime文档声明:Joda-Time在操作期间也分配了很少的临时对象,并且几乎不执行任何线程同步。 在大量多线程或使用大量内存的系统中,Calendar,SimpleDateFormat和TimeZone可能成为瓶颈。 当使用Joda-Time类时,瓶颈就会消失。

解决方法是使用JodaTime库,或修补JDK TimeZone类,或等待Oracle修复问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM