2016-05-26 38 views
0

我在我的应用程序中使用了许多AsyncTask类。我总是开始使用它们:Android - 如何检查ThreadPoolExecutor是否已达到队列限制?

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?

回答

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比蜂窝时,您可以使用

AsyncTaskCompat.executeParallel(task, params); 

从支持v4库。

您可以在此answer

UPDATE找到更多的细节:

检查可用之前执行遗嘱执行人,你可以写一个小功能,像:

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 { 
      //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。

+0

谢谢你的回应,但这不是问题。我已经知道这一点。我正在寻找的是一种类似于'boolean canExecutorAddAnotherQueue()'的方法,我可以使用它来确定是否可以将我的asyncTask添加到Executor线程池中 – Anonymous

+0

请参阅我的更新答案,您可以使用try catch或写入自定义处理程序为您的情况 – Ken

+0

你写的方法似乎更像它。尝试抓住似乎是一个可怜的办法但是我不使用自定义的ThreadPoolExecutor。 AsyncTask使用它自己的。所以MAX_QUEUE_SIZE_YOU_DEFINED是AsyncTask定义的那个。根据我的理解,这取决于设备所具有的内核数量。在我的设备上测试它我发现getQueueSize()是128时抛出异常,但我不知道如何使用API​​获取该数字。 – Anonymous