2016-05-26 10 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(). Но он также ограничен (максимальное количество задач = размер пула потоков + размер очереди задач).

Вы можете создать собственный Исполнитель для увеличения количества потока или очереди задач, как это:

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

Для запуска исполнителя() функции для Android ниже Honeycomb, вы можете использовать

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 или write пользовательский обработчик для вашего дела. – Ken

+0

Метод, который вы написали, больше похож на него. попробуйте поймать, кажется, плохой подход ...Но я не использую пользовательский ThreadPoolExecutor. AsyncTask использует его собственный. поэтому MAX_QUEUE_SIZE_YOU_DEFINED - это тот, который определяет AsyncTask. Что из того, что я понимаю, зависит от количества ядер, которые имеют устройства. Проверяя это на моем устройстве, я увидел, что исключение выбрано, когда getQueueSize() - 128, но я не знаю, как получить этот номер с помощью API. – Anonymous

 Смежные вопросы

  • Нет связанных вопросов^_^