The good news is I was able to implement ScheduledThreadPoolExecutors with relative ease. The bad news is they didn't solve any of the problems we thought they would (with the exception of potential performance improvements, but I didn't notice any). The good news from that, though, is I was able to figure out what was causing (but not solve) the problems we thought were being caused by Timers. The problem didn't have anything to do with the structure of Timers themselves, but rather, the way they were being used.