1

目标:

最后入队okhttp3.Call的先执行


尝试过的解决方案:LIFO Executor(不起作用)

我找到了一个 LIFO 的解决方案Executor带有 LIFO 排序的执行器服务),并通过这种方式将这种应用ExecutorOkHttpClient

private val httpClient = OkHttpClient.Builder().dispatcher(
        Dispatcher(ThreadPoolExecutor(..., LifoLinkedBlockingDequeue<Runnable>()))
    ).build()

但是,这不起作用

分析

在跟踪源代码后okhttp3.Dispatcher,我发现:

  1. 首先,每个入队Call都被添加(private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>())Dispatcher.java
  2. 然后,这些Calls按FIFO顺序从readyAsyncCalls阻塞双端队列中移出Executor
  3. 最后,Calls in以LIFO顺序Executor执行

就我而言,同时产生了巨大Call的 s,并且消耗它们的线程相对较少。
--> 大部分Calls都在排队Dispatcher而不是Executor在某一刻
--> LIFOExecutor不发挥效果

例子

| 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 以 FIFO 顺序从Dispatcher到移动Executor,这个过程非常“低效”。
  • CallExecutor执行状态到执行状态的顺序是 LIFO 顺序。Call但是s中的s很少Executor,LIFO效果不明显。

有谁知道实现这一目标的其他方法?

4

2 回答 2

1

在 OkHttp 的调度程序前构建您自己的 LIFO 队列。它接受调用并保持它们直到它们准备好被执行。当它们出现时,将它们发布在调度程序上。

于 2019-11-03T04:10:36.833 回答
0

Dispatcher我发现将请求从 移动到是无效的原因Executor是:一次移动请求的数量有两个最大值。

// okhttp3.Dispatcher
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
    //do something...    

    if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
    if (runningCallsForHost(asyncCall) >= maxRequestsPerHost) continue; // Host max capacity.
    //do something...
}

溶胶

Dispatcher.maxRequests为和设置更大的值Dispatcher.maxRequestPerHost

这样每个新的传入请求都可以尽快移动到执行器
--> 以充分发挥传入队列的特性Executor

但是...我不确定最大的最大值是否会引起任何副作用...

于 2019-11-04T15:35:55.097 回答