2014-10-14 2 views
0

У меня есть этот сервис:Android темы и услуги

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 
    running = true; 
    new Thread(){ 
     @Override 
     public void run() { 
      super.run(); 
      while (running) { Thread.sleep(60); ... } 
     } 
    }.start(); 
    return super.onStartCommand(intent, flags, startId); 
} 

Я видел этот пример на курсе Android Bootcamp на YouTube и он работал. Мой вопрос: это не опасная вещь? потому что, если служба будет остановлена ​​во время спящего потока, ее память может быть вытеснена GC, а затем поток попытается получить доступ к нераспределенной переменной (работает) ... Я подозреваю, что она работает, потому что она добавляет +1 к счетчику ссылок на работу и почему он будет вытеснен только тогда, когда поток закончится, но я бы хотел, чтобы кто-то подтвердил это и, возможно, дал подробное объяснение этому процессу.

Спасибо !.

ответ

1

, если служба будет остановлена ​​в то время как поток спит его память может быть выселен ГМ

Это предположение неверно.

Могу ли я предложить вам this reading о Java GC. Вот соответствующая цитата:

Активные потоки Java всегда считаются живыми объектами и, следовательно, являются корнями GC.

Так что ваша нить спала, но она все еще находится в рабочем состоянии. Тот факт, что он спит, здесь не важен. Важно то, что поток еще не закончен (как вы сказали в своем вопросе).

Резьба еще не закончена, это значит, что она по-прежнему активна, поэтому поток является GC-корнем.

Поскольку он содержит ссылку на член running: услуга не будет собираться с мусором.

Опасно ли это? Да ! потому что это потенциальная утечка памяти, а не потому, что существует риск доступа к нераспределенной переменной.


Чтобы избежать утечки памяти необходимо убедиться в том, что в какой-то момент: ваш поток завершится (т.е. running стал ложным) ... для каждой возможной ситуации:

  • нормальное выполнение сервиса (из Конечно)
  • неожиданного исключения
  • служба убит OS
+0

Это правильный ответ. Даже если set running = false в onDestroy(), у нас все еще есть потенциальная утечка памяти, если мы не гарантируем завершение потока до выхода onDestroy(). Вот почему мы не используем голый Thread и вместо этого используем конструкции более высокого уровня. –

+0

Спасибо за ответ! каковы эти конструкции более высокого уровня? и как бы вы это сделали без риска утечки памяти? (Я хочу, чтобы служба запускалась и выполняла что-то каждые 60 секунд, пока служба не остановилась). Прочее, определяющее поток в классе обслуживания и остановку его на onDestroy службы. – TomerZ

+0

Вы можете использовать ExecutorService, возвращенный из Executors.newSingleThreadExecutor() для этого. Затем вы можете использовать shutdown() и waitTermination(), чтобы убедиться, что он отключился должным образом. –

0

Поскольку у вас есть работающая нить (она действительно не спит), она содержит ссылку на услугу. Это означает, что доступ к сервису и всему сервису не будет собран и выпущен.

+0

Что вы имеете в виду, что реально не SLE ер?и как статус потока влияет на его способность иметь или не иметь ссылки на объекты в памяти? – TomerZ

+0

while (работает) {Thread.sleep (60); ...} он не спит, он находится в цикле навсегда, основываясь на вашем коде. Thread работает, это исполняемый фрагмент кода, который содержит ссылки и предотвращает сбор мусора. –

+0

Он спящий, в течение 60 секунд из-за 'Thread.sleep (60);'. Эти ссылки - именно то, о чем я спрашиваю, поэтому в момент компиляции jvm проверяет, какие переменные ссылаются внутри потока, и эти переменные имеют «счетчик ссылок» из 2? (из сервиса и из потока) – TomerZ

0

То, что вы разместили, не будет компилироваться без объявления running final. Когда вы объявляете переменную final, новый экземпляр Thread фиксирует значение, и значение останется таким же, как и вне зависимости от того, что происходит снаружи.

Обычно в Java нет доступа к нераспределенной переменной.

+0

На самом деле это было бы: https://www.youtube.com/watch?v=Q9dk82ux-fA&list=PLE08A97D36D5A255F#t=1311 – TomerZ

+0

Это не то, что вы опубликовали. Вы можете отредактировать свой пост, чтобы отразить код, о котором вы просите. –

+0

И в отношении кода, о котором вы спрашиваете, ссылка на переменную экземпляра Службы в текущем потоке не позволит службе быть GC'd. –