I have a program that spawns threads (~5-150) which perform a bunch of tasks. Originally, I used a FixedThreadPool because this similar question suggested they
Both FixedThreadPool and CachedThreadPool are evils in highly loaded applications.
CachedThreadPool is more dangerous than FixedThreadPool
If your application is highly loaded & demands low latency, better to get rid of both options due to below drawbacks
CachedThreadPool to go out of control on Thread creationSince you know that both are evils, lesser evil doesn't do any good. Prefer ThreadPoolExecutor, which provides granular control on many parameters.
beforeExecute(Thread, Runnable) and afterExecute(Runnable, Throwable)