Given that `ScheduledThreadPoolExecutor` is the only implementation in the Java standard library of this, the simplest thing would be to just use that for the dependency instead, even if that's a bit icky. Some other alternatives are:

1. Some sort of marker trait that allows you to remove runnables
2. Wrap the scheduled executor service so that it does the right things on `cancel`.

Sadly, both of these introduce complexity.