AsyncTask、RejectedExecutionException 和任务限制
Posted
技术标签:
【中文标题】AsyncTask、RejectedExecutionException 和任务限制【英文标题】:AsyncTask, RejectedExecutionException and Task Limit 【发布时间】:2011-01-30 09:04:04 【问题描述】:我正在从远程服务器获取大量缩略图,并使用 AsyncTask 在网格视图中显示它们。问题是,我的网格视图一次显示 20 个缩略图,因此创建 20 个 AsyncTask 并启动 20 个执行,每个缩略图一个。
我的代码中出现RejectedExecution
异常。我记得在某处读到 AsyncTask 一次可以在其队列中拥有的任务数量是有限制的,我可能会遇到这个问题。这个栏被取消了吗?
有没有办法增加这个限制?忽略这个异常是否安全?(通过有一个空的catch(RejectedException e)
块?)
我在 android 1.6 模拟器和我的代码中的 API 级别上运行此代码(minSDKVersion 为 3)。 [编辑:添加了 SDK 和 API 级别信息]
【问题讨论】:
【参考方案1】:我记得在某处读过 是对任务数量的限制 AsyncTask 可以在它的队列中有一个 时间,我可能会打那个。曾是 这个栏被取消了吗?
AsyncTask
目前似乎支持 10 个线程和 10 个工作队列深度。理论上,这将只支持 20 个项目...如果没有其他使用 AsyncTask
。
有没有办法提高这个限制?
获取源代码,对其进行修改,将其放入您自己的包中,然后使用那个。我用我的AsyncTaskEx
完成了这项工作,尽管它基于 Android 1.5 源代码。
忽略这一点是否安全 异常?
您的工作不会排队等待执行。这是否“安全”取决于您。我不知道对AsyncTask
基础架构有任何其他影响。
【讨论】:
感谢 Mark 的回复以及分享您的代码!顺便说一句,根据 Romain Guy 的评论:***.com/questions/990948/… 限制似乎已经放宽了。 很遗憾,我无法证实他的说法。我上面的内容来自我对源代码的检查(通过谷歌代码搜索找到)。不过,可能是我误读了代码。 我遇到了同样的问题。我非常乐意让我的任务按顺序而不是并行执行。有没有办法做到这一点?还是我要回去实现一个工作队列? @Edward Falk:正如我上面写的,“获取源代码,修改它,将它放入你自己的包中,然后使用那个。”只需调整 LinkedBlockingQueue 设置以匹配您想要的模式。 +1 获取源代码,修改它,放入你自己的包中,然后使用那个。拯救了我的一天!【参考方案2】:我自己在应用程序中也做过同样的事情。
一次启动 20 个并行线程以从服务器下载缩略图并将其推送到数据适配器对我来说听起来不是一个好主意。所有这些线程只会相互绊倒并相互妨碍。
相反,我将只启动一个线程,让它循环收集缩略图,并在它们到达时将它们添加到适配器。
【讨论】:
【参考方案3】:您可以使用带有 AsyncTask.executeOnExecutor 的串行执行器来序列化您的任务,但这会将任务限制为一次只能执行一个并发任务。获取缩略图时可能会很好:
myAsyncTask.executeOnExecutor(MyAsyncTask.SERIAL_EXECUTOR, [params] );
【讨论】:
【参考方案4】:问题在于AsyncTask.THREAD_POOL_EXECUTOR
的待处理 AsyncTasks 的数量是 128。一旦队列被填满,就不能将新的 AsyncTasks 加入队列。
来自 AsyncTask 源代码:
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
在我看来,限制完全没有意义,AsyncTask.SERIAL_EXECUTOR
有无限队列。
【讨论】:
【参考方案5】:“安全”可以忽略 - 您需要确保当您发现错误时,您计划在执行后执行的任何类型的通知都将在此处完成 - 否则,如果您的其他代码可能会挂起对收到此任务的回音做出假设。
【讨论】:
以上是关于AsyncTask、RejectedExecutionException 和任务限制的主要内容,如果未能解决你的问题,请参考以下文章
AsyncTask 替代背景图像下载? (AsyncTask ---------已弃用)