Потоки AsyncTask никогда не умирают


112

Я использую AsyncTasks для получения данных в ответ на нажатие кнопки пользователем. Это работает хорошо и поддерживает отзывчивость интерфейса при извлечении данных, но когда я проверил, что происходит в отладчике Eclipse, я обнаружил, что каждый раз при создании нового AsyncTask(что довольно часто, потому что их можно использовать только один раз) ), новый поток создавался, но никогда не завершался.

В результате большое количество AsyncTaskпотоков просто сидит там. Я не уверен, является ли это проблемой на практике или нет, но мне бы очень хотелось избавиться от этих лишних потоков.

Как я могу убить эти темы?


Что вы имеете в виду под «никогда не прекращать»? Задача никогда не завершает свой метод doInbackground или вы просто видите объект asynctask в трассировщике распределения?
Francesco Laurita

7
doInBackgroundМетод завершается, но поток продолжает отображаться в окне отладки. Например: Thread [<23> AsyncTask #4](Running)
Computerish

Ответы:


202

AsyncTaskуправляет пулом потоков, созданным с помощью ThreadPoolExecutor. В нем будет от 5 до 128 потоков. Если потоков больше 5, эти дополнительные потоки будут оставаться не более 10 секунд, прежде чем будут удалены. (примечание: эти цифры относятся к видимому в настоящее время открытому исходному коду и зависят от версии Android).

Оставьте AsyncTaskтемы в покое, пожалуйста.


Спасибо за объяснение! Рад знать, что я не делаю ничего плохого. Из любопытства, почему он так устроен? Почему бы просто не завершить потоки после возврата всех методов?
Computerish

7
Предположительно, чтобы сэкономить время на разветвление потоков для последующих запросов.
CommonsWare

@CommonsWare у меня есть служба, в которой я запускаю AsyncTask для выполнения некоторой операции, и служба запускается, когда нажимается кнопка виджета, и когда задача завершена, она должна немедленно остановить службу, но иногда AsyncTask не умирает, поэтому вы можете скажи мне, как мне это остановить
Охота

1
@SreekanthKarumanaghat: Использование a AsyncTaskдля чего-то, что займет так много времени, - вообще плохая идея. Но нет, мой комментарий о том, что лишние потоки исчезают, когда они не используются. Итак, когда одна из ваших 6 задач завершится, ее поток останется в пуле в течение 10 секунд, после чего этот поток будет завершен.
CommonsWare

1
@SreekanthKarumanaghat: «У меня вопрос, есть ли какие-либо ограничения на выполнение 20 (скажем) асинхронных задач в параллельном режиме?» - Значительное использование AsyncTaskсегодняшнего дня - не лучший план. Наличие 20+, которые могут работать в течение 10+ секунд, - это то, что должно провалить проверку кода. Если вы создадите 20 задач в быстрой последовательности, только несколько будут выполняться одновременно, а остальные будут поставлены в очередь для последующего выполнения. Сколько будет запускаться одновременно, зависит от количества ядер ЦП. AFAIK, текущий алгоритм - это 2N + 1 параллельных потоков, где N - количество ядер.
CommonsWare

24

В дополнение к ответу CommonsWare:

В настоящее время я использую Android 2.2, и мое приложение одновременно использует не более одной AsyncTask, но я создаю новую каждые x минут. Сначала начинают появляться новые потоки AsyncTask (новый поток для нового AsyncTask), но после 5 потоков (как указано CommonsWare) они просто остаются видимыми в окне отладки и повторно используются, когда требуются новые потоки AsyncTask. Они просто остаются там, пока отладчик не отключится.


2
Да, подтверждено: я вижу не более 5 AsyncTasks.
Серафим

3

Здесь тот же симптом. В моем случае потоки зависли после того, как я убил Activity, и я надеялся, что приложение полностью закроется. Проблема частично решена за счет использования однопоточного исполнителя:

    myActiveTask.executeOnExecutor(Executors.newSingleThreadExecutor());

Это заставляло нить исчезать после завершения своей работы.


Этот ответ заставил AsyncTask исчезнуть после его запуска, возможно, это не «способ делать что-то в Google», но он выполняет свою работу. Спасибо.
Энрике де Соуза

Это решило мою конкретную проблему, связанную с запуском Asynctasks в одном потоке.
Ло Хименес,

0

Используйте ThreadPoolExecutor .

BlockingQueue workQueue= new LinkedBlockingQueue<Runnable>(100); // Work pool size
ThreadPoolExecutor executor = new ThreadPoolExecutor(
            Runtime.getRuntime().availableProcessors(),       // Initial pool size
            Runtime.getRuntime().availableProcessors(),       // Max pool size
            1, // KEEP_ALIVE_TIME
            TimeUnit.SECONDS, //  KEEP_ALIVE_TIME_UNIT
            workQueue);

Опубликуйте свою Runnableзадачу с помощью метода execute () .

void execute (Runnable command)

Выполняет данную задачу когда-нибудь в будущем. Задача может выполняться в новом потоке или в существующем объединенном потоке.

Что касается вашего второго запроса:

Как я могу убить эти темы?

Как только вы закончите свою работу ThreadPoolExecutor, выключите его должным образом, как указано в сообщении ниже:

Как правильно завершить работу java ExecutorService

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.