18

我的 Android 应用程序必须处理到达的消息,这些消息经常成束出现(尤其是在不稳定的连接期间)。我在 AsyncTasks 中处理这些传入消息,这样我就不会干扰 UI 线程。如果一次收到太多消息,我会收到一个RejectedExecutionException. 我的错误堆栈如下所示:

10-22 14:44:49.398: E/AndroidRuntime(17834): Caused by: java.util.concurrent.RejectedExecutionException: Task android.os.AsyncTask$3@414cbe68 rejected from java.util.concurrent.ThreadPoolExecutor@412716b8[Running, pool size = 128, active threads = 22, queued tasks = 0, completed tasks = 1323]
10-22 14:44:49.398: E/AndroidRuntime(17834):    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1967)
10-22 14:44:49.398: E/AndroidRuntime(17834):    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:782)
10-22 14:44:49.398: E/AndroidRuntime(17834):    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1303)
10-22 14:44:49.398: E/AndroidRuntime(17834):    at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:564)

我正在运行任务,task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)以便并行处理传入的消息。

令人困惑的是,与我可以找到的相关 StackOverflow 问题(例如这里这里)不同的是,活动线程和排队任务的数量似乎并没有超出限制(似乎是 128和 10,分别)。查看堆栈跟踪:

ThreadPoolExecutor@412716b8[Running, pool size = 128, active threads = 22, queued tasks = 0, completed tasks = 1323]

为什么我会收到此错误消息?

4

2 回答 2

29

为什么我会收到此错误消息?

如果ThreadPoolExecutor仍在运行,则仅当您已超过ThreadPoolExecutor. 唯一一次RejectedExecutionException抛出的是ThreadPoolExecutor.AbortPolicy默认的RejectedExecutionHandler

引用javadocs

如果请求无法排队,则会创建一个新线程,除非这将超过 maximumPoolSize,在这种情况下,该任务将被拒绝。

有最大数量的任务。请在此处查看此问题/答案:同时执行的 AsyncTasks 是否有限制?

这是AsyncTask源代码的链接。

private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;

private static final BlockingQueue<Runnable> sWorkQueue =
        new LinkedBlockingQueue<Runnable>(10);

private static final ThreadPoolExecutor sExecutor =
    new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE,
        KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);

所以看起来它从 5 个线程开始,有 10 个队列。一旦队列满了,它最多可以启动 128 个线程。所以看起来你已经超过了 138 个并发请求。

ThreadPoolExecutor@412716b8[正在运行,池大小 = 128,活动线程 = 22,排队任务 = 0,已完成任务 = 1323]

试图抓住ThreadPoolExecutor它用完空间的确切时刻将非常困难,并且它很快就会变成一个黑森错误,因为你越看ThreadPoolExecutor数字,你就越会影响该类的同步和因此,您可能会使该错误消失。

在您的情况下,当您使用有关 TPE 的详细信息记录异常时,条件必须已经通过。

于 2013-10-22T22:16:38.620 回答
11

如果您的 Executor 调用 shutdown 方法,然后您将新的 Task (Runnable) 用于执行,也会发生此异常。喜欢

mThreadPoolExecutor.shutdown();
...
...
...
mThreadPoolExecutor.execute(new Runnable(){...});
于 2014-06-10T06:27:29.190 回答