I spent today trying different ways of utilising concurrency within MetaInspector.
It's tempting because Inspectors are inherently threadsafe and immutable, so they can safely be run in parallel. There's a minor complication with having to make sure the order of merging is maintained, and I had to move some methods from private to protected static to allow access from a private static inner class, but otherwise it wasn't too bad (I mostly just used CyclicBarrier).
Then I noticed it didn't work.
It worked most of the time, but sometimes one or more Inspectors would fail. I tracked this down to not being the Inspector's fault, but the object that was being inspected: some of the getters in my JSF application use lazy-initialization, and some of them use FacesContext while doing so. FacesContext is a non-inheritable ThreadLocal, so isn't available to those Inspectors running on a different Thread.
So you can't just say to MetaInspector 'here are some Inspectors' and 'here's how many Threads to run them across'. Still, you can say 'here are some Inspectors and here are the groups I want you to run them in' and leave it up to the developer to specify which ones can safely run concurrently.
That does work.
However now the inspector-config.xml looks a bit weird. You don't have to use it if you don't want to, but I'm not sure this feature 'carries its own weight' enough to be part of the core API. You have this confusing interface with setInspectors and setConcurrentInspectors, and it may not be clear which ones run when:
There are other interesting approaches too, such as just using concurrency for the merging whilst letting the Inspectors run on the main Thread.
Still, in the interests of K.I.S.S., I'm leaving it all out. It just smells too much like premature optimization. Keen developers can still implement their own ConcurrentMetaInspector if they need to.