Android 个队列等待 API 个请求
Android queue for API requests
我正在 android 上为 VK 社交网络编写客户端。这个社交网络每秒只允许执行 2-3 个请求,当我向不同的方法添加一些请求时,我会遇到异常,例如。 "Too much requests per second"
所以我的问题是:如何制作一个包含 api 个请求的队列,并能够为每个请求设置优先级。
提前致谢!
这是一个有趣的问题,因为在我的应用程序中,我倾向于为每种不同类型的服务器请求使用专用的 AsyncTask
。所以当我读到这个问题时,我在问自己:当每个任务都是一个不知道其他任务的独立组件时,我将如何实现这样的东西?
我可以尝试像@GabeSechan 所说的那样制作一个PriorityQueue
,但这意味着我需要一个后台线程专门用于等待任务出队,然后在执行队列任务的同时执行它们。但是这个线程听起来必须是 Service
,所以我必须添加所有这些基础结构。那么如何调试诸如挂起和竞争条件甚至死锁之类的多线程问题呢?不,谢谢。必须有更简单的方法...
所以我开始思考...限制请求意味着每个请求都需要在特定时间发生。如果不是排队 请求 ,而是排队 次 会怎么样?如果您有一个为请求分配时隙的单身人士怎么办?它会像这样工作:
- 首先调用时隙分配器上的方法来接收时隙。当请求可以执行时,将从现在开始延迟一毫秒给出时隙。
- 如果延迟大于零,调用
Handler.postDelayed()
延迟,使用包含请求逻辑的Runnable
- 延迟后,Handler 处理启动
AsyncTask
的 Runnable 或后台线程来处理请求。
时隙分配器的逻辑如下所示:
public static synchronized long getNextRequestDelay() {
long delay = 0;
long current = System.getCurrentTimeMillis();
if (current > sLastRequestTime + REQUEST_GAP_MILLIS) {
// we don't have any outstanding requests
sLastRequestTime = current;
} else {
// figure out what the delay needs to be
sLastRequestTime += REQUEST_GAP_MILLIS;
delay = sLastRequestTime - current;
}
return delay;
}
现在,我在那里写了一些代码,但我只是将它输入到答案中,所以我什至不会声称它会编译。更不用说您应该使用像 System.nanoTime()
而不是 System.currentTimeMillis()
这样的单调时钟,这样您就不会受到用户更改时钟时间的影响(不要忘记将 GAP 乘以 1000000)。但要点是:
- 最近请求任务的执行时间只有一个(即静态)位置
- 你检查那个时间并在每次分配一个时间段时增加它
- 您需要同步访问分配器方法。 (好吧,毕竟你可能不得不与死锁作斗争。)
很简单。而且我喜欢简单。我的意思是,我真的喜欢简单。
我正在 android 上为 VK 社交网络编写客户端。这个社交网络每秒只允许执行 2-3 个请求,当我向不同的方法添加一些请求时,我会遇到异常,例如。 "Too much requests per second"
所以我的问题是:如何制作一个包含 api 个请求的队列,并能够为每个请求设置优先级。
提前致谢!
这是一个有趣的问题,因为在我的应用程序中,我倾向于为每种不同类型的服务器请求使用专用的 AsyncTask
。所以当我读到这个问题时,我在问自己:当每个任务都是一个不知道其他任务的独立组件时,我将如何实现这样的东西?
我可以尝试像@GabeSechan 所说的那样制作一个PriorityQueue
,但这意味着我需要一个后台线程专门用于等待任务出队,然后在执行队列任务的同时执行它们。但是这个线程听起来必须是 Service
,所以我必须添加所有这些基础结构。那么如何调试诸如挂起和竞争条件甚至死锁之类的多线程问题呢?不,谢谢。必须有更简单的方法...
所以我开始思考...限制请求意味着每个请求都需要在特定时间发生。如果不是排队 请求 ,而是排队 次 会怎么样?如果您有一个为请求分配时隙的单身人士怎么办?它会像这样工作:
- 首先调用时隙分配器上的方法来接收时隙。当请求可以执行时,将从现在开始延迟一毫秒给出时隙。
- 如果延迟大于零,调用
Handler.postDelayed()
延迟,使用包含请求逻辑的Runnable - 延迟后,Handler 处理启动
AsyncTask
的 Runnable 或后台线程来处理请求。
时隙分配器的逻辑如下所示:
public static synchronized long getNextRequestDelay() {
long delay = 0;
long current = System.getCurrentTimeMillis();
if (current > sLastRequestTime + REQUEST_GAP_MILLIS) {
// we don't have any outstanding requests
sLastRequestTime = current;
} else {
// figure out what the delay needs to be
sLastRequestTime += REQUEST_GAP_MILLIS;
delay = sLastRequestTime - current;
}
return delay;
}
现在,我在那里写了一些代码,但我只是将它输入到答案中,所以我什至不会声称它会编译。更不用说您应该使用像 System.nanoTime()
而不是 System.currentTimeMillis()
这样的单调时钟,这样您就不会受到用户更改时钟时间的影响(不要忘记将 GAP 乘以 1000000)。但要点是:
- 最近请求任务的执行时间只有一个(即静态)位置
- 你检查那个时间并在每次分配一个时间段时增加它
- 您需要同步访问分配器方法。 (好吧,毕竟你可能不得不与死锁作斗争。)
很简单。而且我喜欢简单。我的意思是,我真的喜欢简单。