2011-12-14 30 views
0

我有一个web应用程序需要有时从url下载一些字节并将其打包并发送回请求者。下载的字节存储了一段时间,以便在需要下载相同的URL时可以重新使用它们。我试图找出如何最好地防止线程同时下载同一个网址,如果请求同时进入。我正在考虑创建一个如下所示的类,以防止同时下载相同的URL。如果一个url无法被锁定,那么它会等待,直到它不再被锁定,只要它在解锁后不存在,就尝试下载它。在java中创建安全的多线程文件

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

听起来好像你不需要锁,因为如果有多个请求下载相同的URL,是只下载一次。

此外,我认为在封装方面更有意义的是将存储的URL /例程的检查存储在URLDownloader类中的新URL中,而不是在调用类中。您的线索可以简单地呼叫fetchURL(),并让URLDownloader处理细节。

所以,你可以通过两种方式来实现它。如果您没有持续的下载请求流,更简单的方法是只有一个URLDownloader线程正在运行,并且要使其fetchURL方法​​,以便您一次只下载一个URL。否则,请将待处理的下载请求保留在中央LinkedHashSet<String>中,以保留顺序并忽略重复。

1

我会建议保持ConcurrentHashSet<String>来跟踪你的可见的唯一URL您的所有线程。这个构造可能并不直接存在于java库中,但可以通过像这样的ConcurrentHashMap轻松构建:Collections.newSetFromMap(new ConcurrentHashMap<String,Boolean>())