Goal:
Last enqueued okhttp3.Call is executed first
Tried solution: LIFO Executor (not work)
I have found a solution for a LIFO Executor(Executor Service with LIFO ordering), and applied this kind of Executor into OkHttpClient by this way
private val httpClient = OkHttpClient.Builder().dispatcher(
Dispatcher(ThreadPoolExecutor(..., LifoLinkedBlockingDequeue<Runnable>()))
).build()
But, this didn't work.
Analysis
After tracing source code in okhttp3.Dispatcher, I found that:
- First, every enqueued
Callis added into(private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>())inDispatcher.java" - Then, those
Calls are moved fromreadyAsyncCallsto the blocking deque ofExecutorin FIFO order - Finally,
Calls inExecutorare executed in LIFO order
In my case, tremendous Calls are produced at the same time, and there are relatively less threads consuming them.
--> Most Calls are queued in Dispatcher instead of in Executor at a moment
--> LIFO Executor doesn't play the effect
Example
| Dispatcher: 1,2,3,4,5 | Executor: | executing: | done: |
| Dispatcher: 2,3,4,5 | Executor:1 | executing: | done: |
| Dispatcher: 4,5 | Executor:2,3 | executing:1 | done: |
| Dispatcher: 5 | Executor:4 | executing:3,2 | done:1 |
| Dispatcher: | Executor:5 | executing:4 | done:1,3,2 |
| Dispatcher: | Executor: | executing:5 | done:1,3,2,4 |
| Dispatcher: | Executor: | executing: | done:1,3,2,4,5 |
Calls are moved fromDispatchertoExecutorin FIFO order, and this procedure is very "inefficient".Calls fromExecutorto executing state is in LIFO order. But there are fewCalls inExecutor, LIFO effect is not obvious.
Does anyone know other way to achieve this?
Build your own LIFO queue in front of OkHttp’s dispatcher. It accepts calls and holds them until they're ready to be executed. When they are, post them on the dispatcher.