【发布时间】:2014-12-01 05:59:31
【问题描述】:
我一直在写一个文件下载模块,当用户选择一些文件并点击下载按钮时,它会创建与文件一样多的 AsyncTasks。所有这些文件都被添加到一个数组中。然后我遍历数组,为文件创建一个AsyncTask,调用每个AsyncTask实例的execute方法。
我通过下载 20 张照片(每张 1 MB)来测试这个模块,结果它可以成功下载这些文件并且稳定。但是当我添加数千个文件(例如 2000 张照片)进行下载时,问题就来了。
当用户点击下载这 2000 张照片时,它会创建 2000 个 AsyncTasks 并立即调用每个的 execute 方法。我认为这不是最佳实践,甚至不会导致 OOM。因为它同时启动了 2000 个线程,虽然根据官方文档只有前 5 个 AsyncTask 实例会在 Kitkat 上调用它们的doInbackground 方法,但已经创建了 2000 个线程并分配了资源(对吗?),这可能会导致 OOM。
为了获得更好的性能,我计划在队列中管理这些 AsyncTask,只轮询前五个实例并执行它们,任何人都执行完毕,它会发送通知并轮询替代一个,直到所有剩余的 AsyncTask 都已执行。我想知道这样想是否正确。提前致谢!
添加下载任务的方法
/**
* Add a new download task
*/
public int addDownloadTask(Account account,
String repoName,
String repoID,
String path) {
// omit lines...
DownloadTask task = new DownloadTask(account, repoName, repoID, path);
// execute download task serially
task.execute();
return task.getTaskID();
}
循环调用addDownloadTask
for (SeafDirent seafDirent : dirents) {
if (!seafDirent.isDir()) {
File localCachedFile = dataManager.getLocalCachedFile(repoName, repoID, seafDirent.name), seafDirent.id);
if (localCachedFile == null) {
txService.addDownloadTask(account, repoName, repoID, Utils.pathJoin(filePath, seafDirent.name));
}
}
}
【问题讨论】:
-
这样思考的好方法。如果你不介意,可以在这里放一些代码,以便我了解一下。
-
为什么不触发 2000 个 AsyncTask,而是触发一个遍历每次下载的 AsyncTask?
-
你有没有想过一个线程池可以按照你想要的方式管理队列?或者你需要异步任务的 UIRunning 方法吗?这样您就不必重新创建新异步任务的实例 1999 次。会对性能产生影响..
-
我认为迈克的评论很好。我认为很好的技术。
-
@Mike 我需要分别发布下载进度,我使用taskID作为标识符,从上面的代码可以看出。
标签: java android multithreading android-asynctask