我有一个webapp,有时需要从URL下载一些字节并将其打包并发送回请求者。下载的字节存储一段时间,因此如果需要下载相同的URL,则可以重复使用它们。我试图弄清楚如果请求同时进入,如何最好地防止线程同时下载相同的URL。我正在考虑创建一个类似下面的类,以防止同时下载相同的URL。如果一个网址无法锁定,那么它会等待直到它不再被锁定,只要解锁后它不存在就会尝试下载。
public class URLDownloader
{
HashMap<String,String> activeThreads = new HashMap<String,String>();
public synchronized void lockURL(String url, String threadID) throws UnableToLockURLException
{
if(!activeThreads.containsKey(url))
activeThreads.put(url, threadID)
else
throw UnableToLockURLException()
}
public synchonized void unlockURL(String url, String threadID)
{
//need to check to make sure its locked and by the passed in thread
returns activeThreads.remove(url);
}
public synchonized void isURLStillLocked(String url)
{
returns activeThreads.contains(url);
}
}
有没有人有更好的解决方案呢?我的解决方案似乎有效吗?是否有任何开源组件已经很好地完成了我可以利用的?
由于
答案 0 :(得分:1)
我建议您保留一个ConcurrentHashSet<String>
来跟踪您的所有主题可见的唯一网址。此构造可能不直接存在于Java库中,但可以通过ConcurrentHashMap轻松构造,如下所示:Collections.newSetFromMap(new ConcurrentHashMap<String,Boolean>())
答案 1 :(得分:0)
听起来你不需要锁定,因为如果有多个请求下载相同的URL,那么关键是只下载一次。
另外,我认为在封装方面更有意义的是检查存储的URL /例程以在URLDownloader
类中存储新URL,而不是在调用类中。您的主题可以简单地调用fetchURL()
,让URLDownloader
处理细节。
因此,您可以通过两种方式实现此目的。如果您没有持续的下载请求流,更简单的方法是只运行一个URLDownloader
线程,并使其fetchURL
方法synchronized
,以便您只下载一次一个URL。否则,将待处理的下载请求保留在中心LinkedHashSet<String>
中,这会保留顺序并忽略重复。