Страницы

Поиск по вопросам

четверг, 11 октября 2018 г.

Обнуляются ли static поля после уничтожения всех экземпляров класса?

Есть задача: запускать поток(Thread1) 1 раз и только. При этом, другой поток(Thread2) периодически создает нужный поток(Thread1). Из за невозможности контролировать количество, происходит повторение действий. Как решить красиво и правильно я не знаю.
Главный вопрос. Имеем
static Thread myThread;
@Override public void run() { if (myThread != null) { if (isAlive()) { // Если поток есть, и живой, то return. // Т.е. получается поток создался, // но не делая ничего завершился, // а предыдущий, который еще работает.... дорабатывает. return; } } // Если не было return, то поток работает }
Но, я переживаю что произойдет следующее: в потоке код выполняется в while(true) {}, т.е. постоянно. На android. И если из за нехватки памяти или другим причинам ОС она прибьет мой поток(Thread1), то другой поток(Thread2) создает его заново. Происходит код выше, и если static Thread myThread не обнулится, то получится что и не работает нужный поток и другие не смогут начать работу. Метода onDestroy нет не у Thread, не у Runnable интерфейса.
Возможно я предложил очень "некрасивое" решение и делается это совсем не так, если кто знает, подскажите в каком направлении смотреть. Я не совсем понимаю природу работы сборщика мусора в java, и политики работы ОС Android(причины завершить процесс аварийно и т.д.).
P.S. Вопрос вкратце: должен жить 1 поток либо ни одного. Если ни одного нет, иметь возможность запустить 1.
UDP: Такой код вроде работает, не знаю как будет вести себя в нестандартных ситуациях.
public static Thread myThread;
@Override public int onStartCommand(Intent intent, int flags, int startId) { if (myThread == null) { myThread = new Thread(new TaskExecutor(this)); myThread.start(); } else { if (!myThread.isAlive()) { myThread = new Thread(new TaskExecutor(this)); myThread.start(); } } return START_STICKY; }
Первый вариант что я писал, там почему то не срабатывает this.isAlive() внутри потока уже. Возвращает false;
UPD 2: Eugene Krivenja ответ хороший. Но Создавая поток при пересоздании сервиса получается так: Старый сервис создан, создал поток. Потом Сервис умирает (я его сам прибил), но поток функционирует. Сервис пере создается, создает поток - имеем 2 рабочих потока, которые дублируют действия. Статик переменная решила мою проблему, но как ты сказал могут быть необъяснимые действия. Буду думать дальше, как сделать 100% безопасно.


Ответ

Хранить что-либо в статических переменных на Андроид очень не рекомендуется. Могут происходить труднообьяснимые вещи. Все из-за механизма выгрузки-загрузки классов.
Стандартный подход в вашем случае, создать потомка от класса Application и в нем хранить ссылку (не статическую) на поток, а сам поток создавать в onCreate() В этом случае поток система уничтожит вместе с обьектом Application, а при перезапуске приложения Application создается самым первым, соответсвенно и поток будет создан.
Второй вариант с сервисом рабочий, и наверное предпочтительный, только myThread опять же не должен быть статическим и поток уничтожится только вместе с сервисом. Поэтому не стоить перезапускать поток кем-то извне, надо перезапускать сам сервис.
Как-то так. На Андроид кроме констант в статических переменных лучше ничего вообще не иметь.

Комментариев нет:

Отправить комментарий