2016-05-26 58 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