Ok ok -_-
I guess I should restate my statement since I was wrong… I did a new benchmark with thread pooling this time. Thread are usually long lived object so they are copied back and forth by the copying collector in the young generation if you don’t use thread pooling. That create some heavy burden on the GC and it garbages a lot more. Also, creating a thread and starting it take some time, so it decreases performance too. So object pooling can be useful 
New statement : Don’t use object pooling for young objects.
In my first benchmark, I got better result because all objects died as soon as you exited the method. All those objects were easy to garbage by the copying collector since it could just ignore them all and copy only the objects currently alive (which was nearly nothing). Also, the object pooling in that example created a lot of reference from old to young objects which is bad.
On the other hand, in the thread pool benchmark, the thread lived a long time so they were copied back in forth by the copying collector.
In regard to that, using object pooling for particle engine is probably a good idea too because the life of the particles are not so short and so they will be copied back and forth by the copying collector, fill up the young memory space and the GC will do collection a lot.
One thing to note; if you use the wrong size for your object pool you will end up with bad performance (at least for thread). So be careful about the size of your object pool.