1.x: fix ExecutorScheduler and GenericScheduledExecutorService reorder bug#3760
Conversation
| NONE = Executors.newScheduledThreadPool(0); | ||
| NONE.shutdownNow(); | ||
| SHUTDOWN = Executors.newScheduledThreadPool(0); | ||
| SHUTDOWN.shutdown(); |
There was a problem hiding this comment.
Ew
I definitely don't like that library will create executor when this class will be loaded. Even without threads used it looks strange.
Maybe return new each time getInstance()?
There was a problem hiding this comment.
Executors don't start their thread until the first task is submitted.
|
I have trouble understanding how this solve the problem, could you please elaborate? |
|
Yes, ExecutorScheduler's worker needs a helper ScheduledExecutorService with a single thread only. But we don't want all ExecutorSchedulers to wait in a single thread for their time to run. This change, similar to how computation scheduler works, hands out single hreaded ScheduledExecutorServices on demand. |
|
Nice catch.
I vote for |
|
Agree with @zsxwing that correctness is more important than performance. |
|
|
||
| ScheduledExecutorService[] execs = new ScheduledExecutorService[count]; | ||
| for (int i = 0; i < count; i++) { | ||
| execs[i] = Executors.newScheduledThreadPool(count, THREAD_FACTORY); |
There was a problem hiding this comment.
count should be replaced with 1 to guarantee FIFO. Right?
|
Right, I'll fix them shortly. |
3252de0 to
c36456a
Compare
|
Updated. |
|
👍 |
1 similar comment
|
👍 |
1.x: fix ExecutorScheduler and GenericScheduledExecutorService reorder bug
This PR relates to the failure of
errorThrownIssue1685.The underlying problem was with the
GenericScheduledExecutorService. By being multi-threaded, tasks scheduled from the same thread one after the other may get reordered because different worker threads inside the pool could pick them up at the same time. In this case, there is no guarantee they keep their FIFO order.(I currently have no idea how one can use trampolining for this case; subsequent tasks may have any relative delays in respect to each other.)
The solution creates N single threaded
ScheduledExecutorServices and getInstance() hands one of them out. In turnExecutorServicetakes one in its worker upfront.However, there is still the problem when the programmer uses a multi-threaded
ScheduledExecutorServicewithSchedulers.from()when the same issue comes back. A solution to that problem would be to always use the newGenericScheduledExecutorServicefor delaying timed tasks.