Нитки AsyncTask ніколи не вмирають


112

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

Результат - велика кількість AsyncTaskниток, що просто сидять там. Я не впевнений, це проблема на практиці чи ні, але я дуже хотів би позбутися цих зайвих ниток.

Як я можу вбити ці нитки?


Що ви маєте на увазі під "ніколи не припиняється"? Чи ніколи завдання не закінчується методом doInbackground або ви просто бачите об’єкт асинтакта в трекері виділення?
Франческо Лауріта

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

Відповіді:


202

AsyncTaskкерує пулом потоків, створеним за допомогою ThreadPoolExecutor. Він буде мати від 5 до 128 ниток. Якщо є більше 5 ниток, ці зайві нитки будуть триматися навколо не більше 10 секунд, перш ніж їх буде видалено. (зауважте: ці цифри є видимим на сьогодні відкритим кодом та відрізняються від випуску Android).

Залиште AsyncTaskнитки в спокої, будь ласка.


Дякую за пояснення! Я радий знати, що нічого поганого не роблю. З цікавості, чому він спроектований так? Чому б просто не закінчити нитки після повернення всіх методів?
Комп'ютерний

7
Імовірно, щоб заощадити час на вилучення ниток на пізніші запити.
CommonsWare

@CommonsWare У мене є служба, в якій я запускаю AsyncTask, щоб виконати деяку операцію, і служба запускається, коли натискається кнопка віджета, і коли завдання закінчено, воно повинно негайно зупинити сервію, але іноді AsyncTask не вмре, тому може і ти скажи мені, як я зупиняю це
Полювання

1
@SreekanthKarumanaghat: Використання AsyncTaskдля чогось, що займе так довго, загалом погана ідея. Але ні, мій коментар до того, що зайві теми відходять, коли вони не використовуються. Отже, коли одна з ваших 6 задач закінчиться, її нитка залишиться в пулі протягом 10 секунд, після чого ця нитка буде припинена.
CommonsWare

1
@SreekanthKarumanaghat: "Моє запитання: чи є якесь обмеження для запуску 20 (скажімо) AsyncTasks у паралельному?" - AsyncTaskсьогодні суттєво використовувати це не великий план. Маючи 20+, які можуть працювати протягом 10+ секунд, це те, що не може перевірити код. Якщо ви швидко створюєте 20 завдань, одразу запускаються лише декілька, а решта буде поставлена ​​в чергу для подальшого виконання. Скільки запускається відразу, залежить від кількості ядер ЦП. AFAIK, поточний алгоритм становить 2N + 1 паралельних ниток, де N - кількість ядер.
CommonsWare

24

Окрім відповіді CommonsWare:

Наразі я використовую Android 2.2, і моя програма використовує не більше одного AsyncTask в будь-який час, але я створюю новий кожні х хвилин. Спочатку починають з’являтися нові теми AsyncTask (нова тема для нової AsyncTask), але після 5 потоків (як згадує CommonsWare) вони просто залишаються видимими у вікні налагодження та отримують повторне використання, коли потрібні нові теми AsyncTask. Вони просто залишаються там, поки налагоджувач не відключиться.


2
Так, підтверджено: я бачу не більше 5 AsyncTasks.
Серафима

3

Такий же симптом і тут. У моєму випадку теми висіли навколо, коли я вбив діяльність, і я сподівався, що додаток повністю закриється. Задача частково вирішується за допомогою одного різьбового виконавця:

    myActiveTask.executeOnExecutor(Executors.newSingleThreadExecutor());

Це змусило нитку зникнути після завершення її роботи.


Ця відповідь змусила AsyncTask піти після його запуску, можливо, це не "гугл спосіб робити речі", але він виконує роботу. Дякую.
Анріке де Соуза

Це вирішило мою конкретну проблему щодо запуску 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.