在java中创建安全的多线程文件

时间:2011-12-14 01:38:45

标签: java multithreading locking synchronized

我有一个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); 
    }

}

有没有人有更好的解决方案呢?我的解决方案似乎有效吗?是否有任何开源组件已经很好地完成了我可以利用的?

由于

2 个答案:

答案 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>中,这会保留顺序并忽略重复。