|
26 | 26 | import java.nio.ByteBuffer;
|
27 | 27 | import java.util.ArrayDeque;
|
28 | 28 | import java.util.ArrayList;
|
| 29 | +import java.util.HashMap; |
29 | 30 | import java.util.List;
|
| 31 | +import java.util.Map; |
30 | 32 | import java.util.concurrent.ConcurrentLinkedQueue;
|
31 | 33 | import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
32 | 34 |
|
|
39 | 41 | */
|
40 | 42 | public class DefaultByteBufferPool implements ByteBufferPool {
|
41 | 43 |
|
42 |
| - private final ThreadLocal<ThreadLocalData> threadLocalCache = new ThreadLocal<>(); |
| 44 | + private final ThreadLocalCache threadLocalCache = new ThreadLocalCache(); |
43 | 45 | // Access requires synchronization on the threadLocalDataList instance
|
44 | 46 | private final List<WeakReference<ThreadLocalData>> threadLocalDataList = new ArrayList<>();
|
45 | 47 | private final ConcurrentLinkedQueue<ByteBuffer> queue = new ConcurrentLinkedQueue<>();
|
@@ -228,6 +230,7 @@ public void close() {
|
228 | 230 | local.buffers.clear();
|
229 | 231 | }
|
230 | 232 | ref.clear();
|
| 233 | + threadLocalCache.remove(local); |
231 | 234 | }
|
232 | 235 | threadLocalDataList.clear();
|
233 | 236 | }
|
@@ -332,4 +335,29 @@ protected void finalize() throws Throwable {
|
332 | 335 | }
|
333 | 336 | }
|
334 | 337 |
|
| 338 | + // This is used instead of Java ThreadLocal class. Unlike in the ThreadLocal class, the remove() method in this |
| 339 | + // class can be called by a different thread than the one that initialized the data. |
| 340 | + private static class ThreadLocalCache { |
| 341 | + |
| 342 | + Map<Thread, ThreadLocalData> localsByThread = new HashMap<>(); |
| 343 | + |
| 344 | + ThreadLocalData get() { |
| 345 | + return localsByThread.get(Thread.currentThread()); |
| 346 | + } |
| 347 | + |
| 348 | + void set(ThreadLocalData threadLocalData) { |
| 349 | + localsByThread.put(Thread.currentThread(), threadLocalData); |
| 350 | + } |
| 351 | + |
| 352 | + void remove(ThreadLocalData threadLocalData) { |
| 353 | + // Find the entry containing given data instance and remove it from the map. |
| 354 | + for (Map.Entry<Thread, ThreadLocalData> entry: localsByThread.entrySet()) { |
| 355 | + if (threadLocalData.equals(entry.getValue())) { |
| 356 | + localsByThread.remove(entry.getKey(), entry.getValue()); |
| 357 | + break; |
| 358 | + } |
| 359 | + } |
| 360 | + } |
| 361 | + } |
| 362 | + |
335 | 363 | }
|
0 commit comments