I would highly recommend making mappedDocs thread-safe data structure (for example, one from java.util.concurrent ), or perhaps a synchronized wrapper created using Collections.synchronizedList .
I think you're lucky that synchronization works using an anonymous inner class. This works because there is only one instance of it, and there is no other code that mutates mappedDocs .
(Actually, you may have a memory visibility problem, even if there are things. If other threads call MapCallback to add elements, something else needs to be synchronized to mappedDocs after it is built and before the added elements are read.)
The root of the problem is that the anonymous inner class used in this way is kind of like a function, but since creating a new object is a manifest, it is tempting to do things like synchronize on it. But it is rather fragile. If it was reorganized so that multiple AIC instances were created (for example, to process documents from several sources) or different AICs were created (for example, to remove documents from the list if they need to be processed), synchronization on separate AIC instances will be fully broken.
Converting mappedDocs to a thread-safe data structure or shell takes care of the memory visibility problem and the parallel access problem. This allows you to use a simple lambda form and allows you to introduce new operations on mappedDocs no matter what threads are running on it.
source share