001package com.identityworksllc.iiq.common; 002 003import java.util.concurrent.ConcurrentHashMap; 004import java.util.concurrent.ConcurrentMap; 005 006/** 007 * A singleton global object with an internal InheritableThreadLocal, allowing 008 * sharing of cached objects within a single thread. Objects will be garbage 009 * collected when the thread itself is cleaned up, so this should either not 010 * be used or routinely clear()'d in long-running threads. 011 * 012 * Since the ThreadLocal is inheritable, child threads will automatically inherit 013 * any stored values. 014 * 015 * This class exposes the ConcurrentMap interface and can be used as such. 016 */ 017@SuppressWarnings("unused") 018public final class ThreadStorage implements DelegatedConcurrentMap<String, Object>, TypeFriendlyMap<String, Object> { 019 /** 020 * The lock object used for singleton construction 021 */ 022 private static final Object _LOCK = new Object(); 023 024 /** 025 * The singleton object 026 */ 027 private static ThreadStorage _SINGLETON; 028 029 /** 030 * Retrieves the singleton thread storage object, constructing a new one if needed 031 * @return The singleton thread storage object 032 */ 033 public static ThreadStorage get() { 034 if (_SINGLETON == null) { 035 synchronized (_LOCK) { 036 if (_SINGLETON == null) { 037 _SINGLETON = new ThreadStorage(); 038 } 039 } 040 } 041 return _SINGLETON; 042 } 043 044 /** 045 * The InheritableThreadLocal object that stores the local Map data. It will 046 * be initialized with an empty ConcurrentHashMap on first use in a given thread. 047 */ 048 private final ThreadLocal<ConcurrentMap<String, Object>> threadLocal; 049 050 /** 051 * Private constructor to enforce singleton 052 */ 053 private ThreadStorage() { 054 threadLocal = InheritableThreadLocal.withInitial(ConcurrentHashMap::new); 055 } 056 057 /** 058 * Retrieves the delegate, in this case the ThreadLocal map 059 * @return The delegated map object 060 */ 061 @Override 062 public ConcurrentMap<String, Object> getDelegate() { 063 return threadLocal.get(); 064 } 065}