将任务提交给线程池会产生RejectedExecutionException

时间:2011-10-17 01:47:23

标签: android multithreading android-ndk

我正在开发一款在Android NDK中主要运行本机代码的社交游戏。该游戏有3个主要的ndk pthreads:

  1. 游戏主题
  2. 服务器通信线程
  3. 主渲染线程(通过Renderer.onRender调用)
  4. 除此之外,在java方面,我们正在使用AdWhirl,它通过自己的ScheduledExecutorService生成自己的线程,但是我们已经将每个调用都包含在“schedule”,“submit”,“post”,“start”中“等与try-catch块一起捕获RejectedExecutionException。但是,我们提交的每个新版本仍然会出现令人恐惧的RejectedExecutionException

    来自Android Market的堆栈跟踪几乎没有为我留下任何线索,我们的质量保证部门也发现很难确定问题,因为它在测试期间几乎不会发生(只有我们的用户报告崩溃)。它仅影响我们用户的一小部分,但每周仍有超过7,000次崩溃(与安装基数较高相比,这一比例较小)

    java.util.concurrent.RejectedExecutionException
    at         java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1876)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:774)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1295)
    at android.os.AsyncTask.execute(AsyncTask.java:394)
    at c.onProgressUpdate(Unknown Source)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:432)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:123)
    at android.app.ActivityThread.main(ActivityThread.java:4632)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:521)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
    at dalvik.system.NativeStart.main(Native Method)
    
        java.util.concurrent.RejectedExecutionException: pool=128/128, queue=10/10
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1961)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:794)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1315)
    at android.os.AsyncTask.execute(AsyncTask.java:394)
    at c.onProgressUpdate(Unknown Source)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:432)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:123)
    at android.app.ActivityThread.main(ActivityThread.java:3691)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:507)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
    at dalvik.system.NativeStart.main(Native Method)
    
        java.util.concurrent.RejectedExecutionException
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1876)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:774)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1295)
    at android.os.AsyncTask.execute(AsyncTask.java:394)
    at c.onProgressUpdate(Unknown Source)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:432)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:123)
    at android.app.ActivityThread.main(ActivityThread.java:4627)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:521)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
    at dalvik.system.NativeStart.main(Native Method)
    

3 个答案:

答案 0 :(得分:17)

虽然您当然应该尽量保持高效,但是“允许”运行的线程数没有任意限制,这完全取决于您构建代码的方式。

ThreadPoolExecutor非常记录良好,并且是您所看到的问题的起源。我会recommend reading through it,看看

首先,我猜测你是用Ant构建的,并且没有在你的javac节点上使用这些参数:

<javac debug="true" debuglevel="lines,vars,source" />

你或者显然正在使用的混淆器是通常最重要的堆栈跟踪部分而不是输出的原因:

c.onProgressUpdate(Unknown Source)

这是ThreadPoolExecutor.AbortPolicy的当前ICS 4.0.4源代码,因为您可以看到它基本上是一个总是抛出异常的全能:

 /**
 * A handler for rejected tasks that throws a
 * {@code RejectedExecutionException}.
 */

public static class AbortPolicy implements RejectedExecutionHandler {
    /**
     * Creates an {@code AbortPolicy}.
     */
    public AbortPolicy() { }

    /**
     * Always throws RejectedExecutionException.
     *
     * @param r the runnable task requested to be executed
     * @param e the executor attempting to execute this task
     * @throws RejectedExecutionException always.
     */
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        throw new RejectedExecutionException("Task " + r.toString() +
                                             " rejected from " +
                                             e.toString());
    }
}

此外,您将在ThreadPoolExecutor的顶部找到defaultHandler:

private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();

最后,如果你看一下ThreadPoolExecutor的默认构造函数:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         threadFactory, defaultHandler);
}

你会看到它使用AbortPolicy类来实例化自己,这是默认的RejectedExecutionHandler

ThreadPoolExecutor还包含您可以设置为默认值的其他几个RejectedExecutionHandler子类,例如:

  /**
 * A handler for rejected tasks that silently discards the
 * rejected task.
 */
public static class DiscardPolicy implements RejectedExecutionHandler {
    /**
     * Creates a {@code DiscardPolicy}.
     */
    public DiscardPolicy() { }

    /**
     * Does nothing, which has the effect of discarding task r.
     *
     * @param r the runnable task requested to be executed
     * @param e the executor attempting to execute this task
     */
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    }
}

其他3个ThreadPoolExecutor构造函数包含一个处理程序选项,因此您可以使用不同的处理程序创建它的实例,或者创建自己的子类,类似于:

package com.justinbuser;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class NoThrowThreadPool extends ThreadPoolExecutor {

    private static final RejectedExecutionHandler defaultHandler = new AdoptPolicy();

    public NoThrowThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler);
        setRejectedExecutionHandler(defaultHandler);
    }

    public NoThrowThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue,
            ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, defaultHandler);
    }

    public NoThrowThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue,
            RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler);
    }

    public NoThrowThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue,
            ThreadFactory threadFactory, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, defaultHandler);
    }

    public static class AdoptPolicy extends ThreadPoolExecutor.AbortPolicy {

        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString()).printStackTrace();
        }
    }
}

答案 1 :(得分:13)

你必须检查你的代码,它创建的AsyncTask太多了。

policy设置为

private static final int CORE_POOL_SIZE = 1;
private static final int MAXIMUM_POOL_SIZE = 10;
private static final int KEEP_ALIVE = 10; 

注意:这在不同版本的Android

中有所不同

答案 2 :(得分:0)

  

当Executor关闭时,以及当Executor对最大线程和工作队列容量使用有限边界并且已经饱和时,将拒绝方法execute(java.lang.Runnable)中提交的新任务。

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/concurrent/ThreadPoolExecutor.java