There is no "non-concurrency-interest" list, so I post this here :)
I released a library containing a ScheduledExecutorService-like interface to execute runnables either: - "as usual", using a clock tied to system time, and possibly multiple threads (I call it hard scheduling), or - using a virtual clock (which time only advances programmatically, like in the TestScheduler of some reactive frameworks), and sequentially in a single thread (I call it soft scheduling). It's available on gh and sf: - https://github.com/jeffhain/jolikit - https://sourceforge.net/projects/jolikit All the classes are in "jolikit.jar", which only depends on Java 6+ (if you want to load the code in some IDE, some of it (GUI stuffs) won't compile because it depends on other libraries, but you can just delete it). The code also contains a sample that can run either in soft or hard scheduling.
The API is simpler than ScheduledExecutorService, in particular because there is no support for futures or other wait-related capabilities, since it makes no sense to wait when the code is being executed sequentially (it would wait forever). There is also no shutdown() method, because its name would not be appropriate in soft scheduling (and I prefer not expose such life cycle methods on the scheduling interface that gets passed around all over the code). Instead, each scheduler implementation has its own way of being stopped. On the contrary, for hard scheduling implementation, internal scheduling code is in some way a bit more complicated than for ScheduledThreadPoolExecutor, because it handles the case of clocks with controllable time and/or variable time speed (by listening to clock's modifications, and waiting up to a configurable max amount of system time).
It's common to use virtual clocks in simulation (e.g. HLA), but it can also greatly help for testing and debugging (the domain code of) general concurrent systems (even distributed ones, which is what HLA is for): - By running your normally-concurrent treatments in a single thread, you can both run them deterministically (If you take care not to introduce sources of non-determinism such as system-hash-code-dependent iteration orders, Randoms without configured seed, etc.), and as fast as possible, which greatly speeds up tests execution and helps to reach and reproduce eventual bugs (in particular, you can turn all logs on (possibly just before the bug occurs), it should slow things down but not modify the behavior). - You can run benches in soft and in hard scheduling, and measure the overhead and the gain of your multi-threading. - If a bug happens in soft scheduling, you can deduce that it's not concurrency related, and if it only happens in hard scheduling, you can infer that it is.