AsyncTask,RejectedExecutionException和任务限制

15

我正在从远程服务器中获取大量缩略图,并在网格视图中显示它们,使用AsyncTask。问题是,我的网格视图每次显示20个缩略图,因此会创建20个AsyncTasks并开始20个执行,每个缩略图一个任务。

我在代码中遇到了RejectedExecution异常。我记得在某个地方读到过,AsyncTask可以同时拥有的任务数量有限制,我可能达到了这个上限。这个限制被取消了吗?

是否有一种方法可以增加这个限制?只是简单地忽略这个异常(通过一个空的catch(RejectedExecutionException e){}块)是安全的吗?

我在Android 1.6模拟器上运行此代码,并且我的代码中的API级别为3(minSDKVersion为3)。 [编辑:添加了SDK和API级别信息]

5个回答

17

我记得在某个地方看到,AsyncTask队列中的任务数量是有限制的,我可能碰到了这个限制。这个限制现在被取消了吗?

目前AsyncTask似乎支持10个线程和10个工作队列深度。理论上,这只能支持20个任务……如果没有其他东西在使用AsyncTask的话。

有办法增加这个限制吗?

获取源代码,进行修改,放入自己的包中,然后使用修改后的代码。我用我的AsyncTaskEx就是这样做的,但是它基于Android 1.5源代码。

忽略这个异常是否安全?

您的工作不会被排队执行。这是否“安全”取决于您。我不知道对AsyncTask基础设施还有其他影响。


感谢马克的回复,也感谢您分享您的代码!另外,根据Romain Guy在此处的评论:https://dev59.com/NUfSa4cB1Zd3GeqPBv7-,限制似乎已经放宽了。 - Samuh
很遗憾,我无法确认他的陈述。我所拥有的是通过谷歌代码搜索发现的源代码检查结果。虽然这可能是我误读了代码。 - CommonsWare
我遇到了同样的问题。我很乐意让我的任务按顺序而不是并行执行。有什么方法可以做到这一点吗?还是我要回去实现一个工作队列? - Edward Falk
@Edward Falk:就像我之前所写的那样,“获取源代码,进行修改,将其放入您自己的包中,并使用该包。”只需调整LinkedBlockingQueue的设置以匹配您所需的模式即可。 - CommonsWare
1
抓取源代码,修改它,将其放入自己的包中,并使用那个。这拯救了我的一天! - stk
你是否考虑/添加了这种代码?if (Build.VERSION.SDK_INT >= 11) { myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, stuff); } - thecr0w

7
我曾经在一个应用程序中做过完全相同的事情。
同时启动20个并行线程从服务器下载缩略图并将它们推送到数据适配器中,这对我来说不是一个好主意。所有这些线程只会互相干扰和阻碍彼此。
相反,我会启动一个线程,在循环中收集缩略图,并在其到达时将它们添加到适配器中。

2
问题在于AsyncTask.THREAD_POOL_EXECUTOR待处理AsyncTasks数量为128。一旦队列填满,就无法排队新的AsyncTasks。
来自AsyncTask源代码:
private static final BlockingQueue<Runnable> sPoolWorkQueue =
        new LinkedBlockingQueue<Runnable>(128);

在我看来,这个限制完全没有意义,而AsyncTask.SERIAL_EXECUTOR则具有无限队列。


2

您可以使用AsyncTask.executeOnExecutor中的串行执行器来序列化您的任务,但这将限制任务一次只能执行一个并发任务。当获取缩略图时可能会很有用:

myAsyncTask.executeOnExecutor(MyAsyncTask.SERIAL_EXECUTOR, [params] );


1
“安全”忽略 - 您需要确保在捕获错误时完成您计划在后执行中进行的任何通知,否则,如果您的其他代码假定从此任务中听到回复,则可能会留下一些未完成的事情。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接