在 SimpleDateFormat 与 clone 上进行同步
2022-09-03 05:51:51
如果您创建了一个类,该类将使用以轮循机制方式预先创建的 SimpleDateFormat 对象的固定大小池来格式化日期,该怎么办?鉴于无争议的同步很便宜,这可能会在 SimpleDateFormat 对象上进行同步,从而在整个集合中摊销冲突。
因此,可能有 50 个格式化程序,每个格式化程序依次使用 - 冲突,因此,只有当 51 个日期实际同时格式化时,才会发生锁争用。
编辑 2011-02-19 (PST)
我按照上面的建议实现了一个固定池,其代码(包括测试)可在我的网站上找到。
以下是在Java 6 SE客户端JVM中运行的四核AMD Phenom II 965 BE的结果:
2011-02-19 15:28:13.039 : Threads=10, Iterations=1,000,000
2011-02-19 15:28:13.039 : Test 1:
2011-02-19 15:28:25.450 : Sync : 12,411 ms
2011-02-19 15:28:37.380 : Create : 10,862 ms
2011-02-19 15:28:42.673 : Clone : 4,221 ms
2011-02-19 15:28:47.842 : Pool : 4,097 ms
2011-02-19 15:28:48.915 : Test 2:
2011-02-19 15:29:00.099 : Sync : 11,184 ms
2011-02-19 15:29:11.685 : Create : 10,536 ms
2011-02-19 15:29:16.930 : Clone : 4,184 ms
2011-02-19 15:29:21.970 : Pool : 3,969 ms
2011-02-19 15:29:23.038 : Test 3:
2011-02-19 15:29:33.915 : Sync : 10,877 ms
2011-02-19 15:29:45.180 : Create : 10,195 ms
2011-02-19 15:29:50.320 : Clone : 4,067 ms
2011-02-19 15:29:55.403 : Pool : 4,013 ms
值得注意的是,克隆和池化非常接近。在重复运行中,克隆比池化更快,因为它的速度更慢。当然,该测试是为极端争用而设计的。
在SimpleDateFormat的特定情况下,我想我可能会想创建一个模板并按需克隆它。在更一般的情况下,我可能会想用这个池来做这些事情。
在以某种方式做出最终决定之前,我想对各种JVM,版本以及各种此类对象进行全面测试。较旧的JVM以及手持设备和手机等小型设备上的JVM在对象创建和垃圾回收方面可能会产生更多的开销。相反,它们在无争议的同步中可能会产生更多开销。
FWIW,从我对代码的审查来看,SimpleDateFormat似乎最有可能在克隆方面做最多的工作。
编辑 2011-02-19 (PST)
同样有趣的是未关注的单线程结果。在这种情况下,池的性能与单个同步对象相当。这意味着池是整体上的最佳选择,因为它在满足和未保持时提供出色的性能。有点令人惊讶的是,克隆在单线程时不太好。
2011-02-20 13:26:58.169 : Threads=1, Iterations=10,000,000
2011-02-20 13:26:58.169 : Test 1:
2011-02-20 13:27:07.193 : Sync : 9,024 ms
2011-02-20 13:27:40.320 : Create : 32,060 ms
2011-02-20 13:27:53.777 : Clone : 12,388 ms
2011-02-20 13:28:02.286 : Pool : 7,440 ms
2011-02-20 13:28:03.354 : Test 2:
2011-02-20 13:28:10.777 : Sync : 7,423 ms
2011-02-20 13:28:43.774 : Create : 31,931 ms
2011-02-20 13:28:57.244 : Clone : 12,400 ms
2011-02-20 13:29:05.734 : Pool : 7,417 ms
2011-02-20 13:29:06.802 : Test 3:
2011-02-20 13:29:14.233 : Sync : 7,431 ms
2011-02-20 13:29:47.117 : Create : 31,816 ms
2011-02-20 13:30:00.567 : Clone : 12,382 ms
2011-02-20 13:30:09.079 : Pool : 7,444 ms
由于 ThreadLocal 在您的情况下是不可能的,因此您应该使用池。获取或创建一个新实例,使用它,然后将其放入池中。