001
014
015 package com.liferay.portal.kernel.util;
016
017 import java.util.HashMap;
018 import java.util.Map;
019 import java.util.concurrent.atomic.AtomicInteger;
020
021
024 public class CentralizedThreadLocal<T> extends ThreadLocal<T> {
025
026 public static void clearLongLivedThreadLocals() {
027 _longLivedThreadLocals.remove();
028 }
029
030 public static void clearShortLivedThreadLocals() {
031 _shortLivedThreadLocals.remove();
032 }
033
034 public static Map<ThreadLocal<?>, Object> getLongLivedThreadLocals() {
035 return _longLivedThreadLocals.get();
036 }
037
038 public static Map<ThreadLocal<?>, Object> getShortLivedThreadLocals() {
039 return _shortLivedThreadLocals.get();
040 }
041
042 public static void setThreadLocals(
043 Map<ThreadLocal<?>, Object> longLivedThreadLocals,
044 Map<ThreadLocal<?>, Object> shortLivedThreadLocals) {
045
046 _longLivedThreadLocals.set(longLivedThreadLocals);
047 _shortLivedThreadLocals.set(shortLivedThreadLocals);
048 }
049
050 public CentralizedThreadLocal(boolean shortLived) {
051 _shortLived = shortLived;
052
053 if (shortLived) {
054 _hashCode = _shortLivedNextHasCode.getAndAdd(_HASH_INCREMENT);
055 }
056 else {
057 _hashCode = _longLivedNextHasCode.getAndAdd(_HASH_INCREMENT);
058 }
059 }
060
061 @Override
062 public T get() {
063 Map<ThreadLocal<?>, Object> threadLocals = _getThreadLocals();
064
065 T value = (T)threadLocals.get(this);
066
067 if (value == _nullHolder) {
068 return null;
069 }
070
071 if (value == null) {
072 value = initialValue();
073
074 if (value == null) {
075 threadLocals.put(this, _nullHolder);
076 }
077 else {
078 threadLocals.put(this, value);
079 }
080 }
081
082 return value;
083 }
084
085 @Override
086 public int hashCode() {
087 return _hashCode;
088 }
089
090 @Override
091 public void remove() {
092 Map<ThreadLocal<?>, Object> threadLocals = _getThreadLocals();
093
094 threadLocals.remove(this);
095 }
096
097 @Override
098 public void set(T value) {
099 Map<ThreadLocal<?>, Object> threadLocals = _getThreadLocals();
100
101 if (value == null) {
102 threadLocals.put(this, _nullHolder);
103 }
104 else {
105 threadLocals.put(this, value);
106 }
107 }
108
109 private Map<ThreadLocal<?>, Object> _getThreadLocals() {
110 if (_shortLived) {
111 return _shortLivedThreadLocals.get();
112 }
113 else {
114 return _longLivedThreadLocals.get();
115 }
116 }
117
118 private static final int _HASH_INCREMENT = 0x61c88647;
119
120 private static final AtomicInteger _longLivedNextHasCode =
121 new AtomicInteger();
122 private static final ThreadLocal<Map<ThreadLocal<?>, Object>>
123 _longLivedThreadLocals = new MapThreadLocal();
124 private static final Object _nullHolder = new Object();
125 private static final AtomicInteger _shortLivedNextHasCode =
126 new AtomicInteger();
127 private static final ThreadLocal<Map<ThreadLocal<?>, Object>>
128 _shortLivedThreadLocals = new MapThreadLocal();
129
130 private static class MapThreadLocal
131 extends ThreadLocal<Map<ThreadLocal<?>, Object>> {
132
133 @Override
134 protected Map<ThreadLocal<?>, Object> initialValue() {
135 return new HashMap<ThreadLocal<?>, Object>();
136 }
137
138 }
139
140 private final int _hashCode;
141 private final boolean _shortLived;
142
143 }