在我正在开发的这个应用程序中,我正在缓存在线音频等内容。在应用程序中的某些点,我对应用程序预测用户很快将需要的内容进行批量下载。所有这些都是通过我自己的缓存系统和后台线程完成的。它的基本要点是,我向缓存发送 url,它会哈希为文件名,然后我们搜索该文件的正确位置,如果存在,我们返回找到的文件的位置,如果不存在,我们下载文件,然后返回文件的位置。当我执行批处理操作时,我将它们放入队列中,这样它们就不会堵塞线程池并导致无法完成其他更高优先级的异步任务。这样,由于队列在完成前一个任务后运行一个新的异步任务,如果设备无法运行多个任务,那么我现在需要完成的任务将是下一个任务。
这就是问题所在。
如果我当前正在将某个音频文件写入 SD 卡,如果我在队列运行时请求它,会发生什么?两个线程可以尝试同时写入同一个文件吗?
或者它会找到该文件,并返回一个半创建且损坏的文件吗?
我该如何避免这种情况?
我想过可能通过优先级队列运行所有内容,但是对于能够运行多个异步线程的设备,这将造成更严格的瓶颈。
编辑:
我的应用程序涵盖 Android 2.3-current
根据这个线程 Running multiple AsyncTasks at the same time -- not possible?
看起来,根据操作系统/设备版本,任务可能会并行运行(一次全部运行到一定限度)或一次运行一个。
xD 这就是为什么我尝试自己管理它们。
最佳答案
您可以使用 ConcurrentHashMap避免多线程写入同一个文件的问题。
ConcurrentHashMap<String, Boolean> map = new ConcurrentHashMap<>();
public void writeToFile(String fileName, byte[] data) {
// putIfAbsent returns the value previously associated with fileName, or null
if(map.putIfAbsent(fileName, Boolean.TRUE) == null) {
try(FileOutputStream stream = new FileOutputStream(fileName)){
stream.write(data);
} finally {
map.remove(filename);
}
}
}
只要所有线程都使用 putIfAbsent
防护,这将防止多个线程写入同一文件名。
关于java - 缓存和线程问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16322231/