Firebase存储RejectedExecutionException异常

时间:2019-03-18 20:28:53

标签: java android firebase firebase-storage

在我的项目中,我正在使用Firebase Storage下载一些图像文件-精确到154张图像。出于某种未知的原因,我只能下载约130个文件,然后出现异常说明:

java.util.concurrent.RejectedExecutionException: Task com.google.firebase.storage.zzs@15c1d59d rejected from java.util.concurrent.ThreadPoolExecutor@270bfa12[Running, pool size = 3, active threads = 3, queued tasks = 128, completed tasks = 5]
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2011)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:793)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1339)
    at com.google.firebase.storage.zzu.zzv(Unknown Source)
    at com.google.firebase.storage.FileDownloadTask.schedule(Unknown Source)
    at com.google.firebase.storage.StorageTask.zzcny(Unknown Source)
    at com.google.firebase.storage.StorageReference.getFile(Unknown Source)
    at com.google.firebase.storage.StorageReference.getFile(Unknown Source)

我正在使用for循环调用StorageReference.getFile()并在特定位置下载文件,如下所示:

        for (int i = 0; i < filesToDownload.size(); i++) {
            String image = filesToDownload.get(i);

            final File localFile = new 
               File(DeviceStorage.getExternalStorageDir(dirPath)
               + File.separator + fileName);
            StorageReference downloadPhotoRef = 
               getReference().child(folderName + File.separator + fileName);

            downloadPhotoRef.getFile(localFile);
            downloadFile(context, image);
        }

我真的很困惑为什么会这样。我找不到任何解决方案,其他人也遇到同样的问题。 我在服务中运行此代码。我不会收到此错误的唯一方法是下载的文件少于130个,但这对我不利。

请帮助。

1 个答案:

答案 0 :(得分:2)

您正在启动太多并行下载任务。结果,线程系统放弃了。有关此内容的更多信息:https://stackoverflow.com/a/8183463/679553

您应该尝试序列化此过程的各个部分,也许可以10乘10的方式下载它们? .continueWith()这是一个好的开始:https://firebase.googleblog.com/2016/09/become-a-firebase-taskmaster-part-3_29.html

目前,您的getFile()调用产生了一个新的下载任务,并且返回时没有阻塞。您可以使用.continueWith()在上一次下载完成后开始下载,而不必通过for循环的下一次迭代开始下一次下载。

一种实现方法是创建一个函数,该函数返回任务并在最后一个continueWith块中调用自身。有点像这里的C#示例形式:https://stackoverflow.com/a/49043177/679553

我修改了该链接中的示例,使其更接近您的情况。我正在移动设备上,所以这是目前最好的操作:)您可以将ref设置为班级中的一个字段,并在continueWith块中进行更新。

Task DoStuff()
{
    return ref.getFile(() => DoWork1())
        .ContinueWith((t1) => DoWork2())
        .ContinueWith(t2 => DoWork3())
        .ContinueWith(t3=> DoStuff());
}