Android - 如何检查ThreadPoolExecutor是否已达到队列限制?

时间:2016-05-26 01:07:42

标签: android android-asynctask task-queue threadpoolexecutor

我在我的应用程序中使用了许多AsyncTask类。我总是使用以下方式开始它们:

if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
    asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
    asyncTask.execute();
}

最近我收到了RejectedExecutionException异常。我读到了这一点并理解为什么会发生这种情况(超过线程池执行程序在其队列中可以拥有的最大任务数)。

但我没有在任何地方读到有关检查线程池执行程序是否有可用插槽的方法,以便我可以避免这种情况。从我测试的asyncTask.execute();方法没有这个限制。

所以我正在寻找这样的事情:

if(executorCanHandlerAnotherQueue()){ 
    if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
        asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    } else {
        asyncTask.execute();
    } 
}
else{
    asyncTask.execute();
}

关于如何实现此功能的任何想法都具有向后兼容性,直至API 9?

1 个答案:

答案 0 :(得分:0)

AsyncTask使用线程池模式,因此它只提供默认的线程数。如果调用execute(),任务将等待工作线程自由执行。

要以真正的并行方式执行,可以调用executeOnExecutor()。但它也是有限的(最大任务数=线程池大小+任务队列大小)。

您可以创建一个自定义Executor来增加线程或任务队列的数量,如下所示:

public static final Executor CUSTOM_THREAD_POOL_EXECUTOR
        = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

对于运行Android低于HONEYCOMB的executor()函数,可以使用

AsyncTaskCompat.executeParallel(task, params);

来自support v4库。

您可以在此answer

中找到更多详细信息

更新:

为了在执行之前检查可用的执行程序,你可以编写一个类似的小函数:

    boolean canExecutorAddAnotherQueue(ThreadPoolExecutor executor){
        int active = executor.getActiveCount();
        int corePoolSize = executor.getCorePoolSize();
        int poolSize = executor.getPoolSize();
        if (active < corePoolSize || active < poolSize) return true;
        int queueSize = executor.getQueue().size();
        if (queueSize < MAX_QUEUE_SIZE_YOU_DEFINED) return true;
        return false;
    }

但它可能会错过一些也被接受的案例。

最终答案:

所以我发现最好的选择是使用try catch:

        try {
            //execute asynctask
        } catch (RejectedExecutionException e){
            //Handle when has exception thrown
        }

或使用自定义处理程序:

    public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)

您可以编写自己的处理程序来处理任务被拒绝的案例,而不再抛出RejectedExecutionException。