gpt4 book ai didi

Java Hashmap 之类的数据结构,在获取时锁定键值对并在放回时解锁 - 为了爬虫的礼貌

转载 作者:行者123 更新时间:2023-11-29 05:23:50 26 4
gpt4 key购买 nike

原始问题:我有一个多线程爬虫应用程序。在此我需要确保目标服务器不会被请求淹没。因此,为了实现这一点,我需要确保对特定域的连续请求以一定的间隔(比如 200 毫秒)发生。

我的解决方案:作为这个问题的一个天真的解决方案,我想到维护一个域名映射到上次请求时间。如果要向某个域发出新请求,我会从 map 中检查上次请求的时间,并将请求延迟必要的时间,以确保在请求之间保持间隔。

当前解决方案和修复中的缺陷:但是如果两个或多个线程在给定时间点请求相同的主域,这个天真的修复将失败。因为所有的线程都会 hibernate 到这个时间间隔并同时发出请求,这会使目标服务器被请求淹没。
修复:我正在考虑的修复是在获取时锁定 map 的键,因此所有其他线程将等待并在放置时解锁,以便下一个等待线程可以继续。

这是解决问题的正确方法吗?如果是这样,我们有没有像这样实现的 map 数据结构?
或者有更好的方法来解决这个问题吗?

最佳答案

您可以对 map 方法进行简单的调整来解决您的问题。首先,我展示一些代码,然后我会解释它:

class Scheduler {
private final Map<String, Long> map = new HashMap<>();
private final long interval = 200; // ms
public void sleepAsLongAsNecessary(String key) {
long now = System.currentTimeMillis();
long deadline = next(now, key);
while (now < deadline) {
Thread.sleep(deadline - now);
now = System.currentTimeMillis();
}
}
private synchronized long next(long now, String key) {
Long oldValue = map.get(key);
long newValue = oldValue == null ? now : Math.max(oldValue + interval, now);
map.put(key, newValue);
return newValue;
}
}

这看起来与您描述的解决方案非常相似。重要的区别是:

map 不存储上次请求时间。相反,它存储请求请求时间的最后一个线程的计划请求时间。如果多个线程同时请求一个请求时间,则每个线程都会得到不同的计划请求时间。

一旦线程知道其计划的请求时间,它就会根据需要 hibernate 。

关于Java Hashmap 之类的数据结构,在获取时锁定键值对并在放回时解锁 - 为了爬虫的礼貌,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23525138/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com