1

In a library, I have some ThreadLocal variable with some objects. I want to accumulate all these objects in one data structure and be able to iterate over them when needed. One the other hand, I don't want this data structure get polluted (additionally, this could potentially lead to memory leaks) when application scenario includes creation and death of thousands of threads. So the solution should clean data structure from objects, local to dead threads.

I think solution should be similar to WeakHashMap with WeakReference<Thread> in keys, which should additionally check if the Thread is not alive in the regular expunge procedure. Iteration is perfromed over Map.values().

Are there are existing implementations of such data structure? Or there are some better solutions for my problem?

leventov
  • 14,760
  • 11
  • 69
  • 98
  • So, you don’t actually want to “accumulate all these objects”, but only be able to iterate over the existing objects associated with a live thread? Did I get that correctly? – Holger Oct 07 '16 at 16:35
  • @Holger I solved this here: https://github.com/OpenHFT/Chronicle-Map/blob/223b2d43299cf94ae9095719341cf84d8f6e5106/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java#L1015-L1043 – leventov Oct 07 '16 at 16:38
  • That `pseudoCollectionForExpunge` is a strange hack…I mean, writing a questionable dummy class (~20 lines of code) to be able to use `removeAll` instead of writing a straight-forward loop doing the same (~3 lines of code)? By the way, if you use a [`ReferenceQueue`](https://docs.oracle.com/javase/8/docs/api/?java/lang/ref/ReferenceQueue.html) you can directly remove the collected references without querying all existing… – Holger Oct 07 '16 at 16:45
  • @Holder haha, this is because removeAll() from array list is optimised (linear complexity), while outside loop will have quadratic – leventov Oct 07 '16 at 16:47
  • @Holger but it definitely deserves a comment in the source, thanks. – leventov Oct 07 '16 at 16:48
  • Oh, I didn’t look for the type but rather assumed that you use a `HashSet`, as you talked about thread to object associations, which implies that there is no guaranteed order anyway… As said, using a reference queue, you could remove cleared references directly, which, of course, would benefit from using a `HashSet`… – Holger Oct 07 '16 at 16:51
  • With Java 8, you could use `allContexts.removeIf(ref -> { ChainingInterface context = ref.get(); return context == null || !context.owner().isAlive(); }`, if you stick to the existing logic, and still avoid the quadratic complexity of an external loop. – Holger Oct 07 '16 at 16:56
  • @Holger I considered this.. removeIf() is implemented differently from removeAll(), it allocates bitset. On each call. RemoveAll - don't. I wanted to avoid allocations. – leventov Oct 07 '16 at 17:02
  • I doubt that you will ever notice an impact of the local bitset allocation. However, if you really care about performance, use a `HashSet` and a reference queue to avoid having to iterate over all entries in the first place. Even with the original logic, a `HashSet` can remove entries without having to shift subsequent entries… – Holger Oct 07 '16 at 17:07

0 Answers0