Нитки 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.