[en] Fix irregularity of Java Timer and ScheduledThreadPoolExecutor

Using Java Timer class one can sche­du­le a task for recur­ring exe­cu­tion. Even tho­ugh Sche­du­led­Th­re­ad­Po­olE­xe­cu­tor makes it possi­ble to cre­ate timers with nano­se­cond reso­lu­tion (but bewa­re of under­ly­ing ope­ra­ting sys­tem clock pre­ci­sion!), regu­la­ri­ty of task exe­cu­tion is by default awful.

I have run into this once and had to expla­in the custo­mer that it’s not fixa­ble. When I measu­red the delay betwe­en timer exe­cu­tions, etc. it tur­ned out that doing as much as new Thread(runnable).start() usu­al­ly takes 1 – 5 mil­li­se­conds, but at times it takes two orders of magni­tu­de lon­ger: even half a second!

Same custo­mer, other pro­ject and this time I tho­ught of a reason for this beha­vio­ur: gar­ba­ge col­lec­tion. I star­ted with cal­ling System.gc() expli­ci­tly insi­de measu­red code and it takes 200 – 500 mil­li­se­conds! So it must be it.

Is the­re a solu­tion? Of cour­se the­re is. It’s cal­led The Con­cur­rent Low Pau­se Col­lec­tor and has been in Java sin­ce ver­sion 5. Read the lin­ked artic­le for many, many deta­ils, but shor­tly just add:

-XX:+UseConcMarkSweepGC

to the usu­al java ‑jar com­mand and the gar­ba­ge col­lec­tion will be done in paral­lel with your code exe­cu­tion. Of cour­se it’s no gol­den bul­let, it makes ove­rall per­for­man­ce wor­se (now inste­ad of 1 – 5 mil­li­se­conds, a sin­gle loop pass takes 4 – 10 mil­li­se­conds), but for this par­ti­cu­lar use, it makes Timer regu­la­ri­ty bet­ter by two orders of magnitude.