title: Caching JDK TimeZone instances
body: <p>We're facing significant performance issues with TimeZone::getTimeZone(String) being a complete bottleneck. It is taking a lock on the class itself (since the method is static), and currently almost all execution threads are waiting to acquire this lock.</p>
  
  <p>I came up with the following solution. It is proven to be a great boost to performance.</p>
  
  <pre><code>private static final Object TIME_ZONE_CACHE_LOCK = new Object();
  private static volatile Map&lt;String, TimeZone&gt; ourCachedTimeZones = new HashMap&lt;&gt;();
  
  public static TimeZone getTimeZoneFor(String timeZoneId)
  {
      TimeZone timeZone = ourCachedTimeZones.get(timeZoneId);
  
      if (timeZone == null)
      {
          TimeZone newTimeZone = TimeZone.getTimeZone(timeZoneId);
  
          synchronized (TIME_ZONE_CACHE_LOCK)
          {
              timeZone = ourCachedTimeZones.get(timeZoneId);
  
              if (timeZone == null)
              {
                  timeZone = newTimeZone;
                  Map&lt;String, TimeZone&gt; cachedTimeZones = new HashMap&lt;&gt;(ourCachedTimeZones);
                  cachedTimeZones.put(timeZoneId, timeZone);
                  ourCachedTimeZones = cachedTimeZones;
              }
          }
      }
  
      // Clone is needed since TimeZone is not thread-safe
      return (TimeZone) timeZone.clone();
  }
  </code></pre>
  
  <p>The question I have: Does anyone know whether or not it is safe to cache TimeZone instances outside the TimeZone class? Meaning that TimeZone/ZoneInfo/ZoneInfoFile does some magic to internally update its cache so that the application cache I have here is not coherent with the one inside TimeZone.</p>
  
  <p>And before someone suggests - it is not an option to upgrade to JDK 8 Date/time API, nor Joda time.</p>
  
  <p>And before someone complains :-) - I know the double-check idiom is usually not recommended.</p>