В одном из наших приложений мы используем фоновый сервис с уведомлением (в основном это сервис переднего плана, но вы понимаете, что активность близка, а сервис остается активным.)
В этом сервисе мы используем3 отдельных HandlerThreads
с Handlers
для управления различными операциями с некоторой задержкой (например, 250 миллисекунд).Теперь эти действия должны быть остановлены, если экран выключен, и возобновлены, если экран снова включается, из-за этой ситуации мы добавили в службу широковещательный приемник и создали-удалили потоки.Пока все работает нормально.
Чтобы остановить операции, мы удалили сообщения на обработчиках, вызвав Handler.removeCallbacksAndMessages(null)
, и это фактически очищает очередь сообщений. Однако поток обработчика остается живым. И это проблема.
Чтобы остановить поток, мы использовали HandlerThread.quit()
, который внутренне вызывает Looper.quit()
, который, как мы думали, будетЗавершить поток, но нет, сэр, он не удаляет поток, потому что мы получаем некоторые отчеты из Fabric, которые отправляются pthread_create failed (1040kb stack), try again
или что-то в этом роде.Под ней было 940 отдельных потоков с одинаковыми именами, что вызвало ошибку OOM (Out of Memory). Это была огромная ошибка с нашей стороны.
Вопрос: как мы можемостановить обработчик потоков?Хватит ли HandlerThread.interrupt()
?Любая помощь приветствуется, спасибо.PS: я не могу поделиться какими-либо исходными кодами, и в этой ситуации я не думаю, что это необходимо, поскольку сам вопрос не требует пояснений.
Редактировать: Поскольку вы попросили какой-то код, я показываюПример некоторой логики, которой я следую.
public class ThreadHelper implements Runnable
{
private HandlerThread handlerThread = new HandlerThread("ThreadName");
private Handler handler;
private boolean shouldRun = true;
public ThreadHelper()
{
handlerThread.start();
startThread();
}
// Called if the screen state is turned on.
public void startThread()
{
if (handlerThread == null)
{
handlerThread = new HandlerThread("ThreadName");
handlerThread.start();
}
if (handler == null)
{
handler = new Handler(handlerThread.getLooper());
handler.post(this);
}
}
// Called if the screen state is turned off.
public void stopThread()
{
shouldRun = false;
handler.removeCallbacksAndMessages(null);
handlerThread.quit();
try
{
handlerThread.interrupt();
}
catch (Exception ignored)
{
// Skipped Thread.currentThread().interrupt() check here since this is
// called from a different thread that is not associated.
}
// remove variables.
handler = null;
handlerThread = null;
}
@Override
public void run()
{
if (shouldRun)
{
// rest of the code without having a long-running
// operation. Mostly ends in 1~2 millseconds.
// Continue looping.
handler.postDelayed(this, 250);
}
}
}