2013-05-01 5 views
7

Załóżmy, że planuję użyć jednej executorservice w całej mojej aplikacji, do której wysyłam nowe runnable lub callable's do wykonania/przesłania, i wycofuję się zaraz po tym, jak to zrobię . Chcę tylko rzucić moje "zadania" do executorservice i pozwolić mu je obsłużyć i wykonać je, podając jego zasoby (ile wątków ma dostępnych i ilu może utworzyć, jeśli to konieczne, a następnie odpowiednio je obsadzić).Kiedy należy wyłączyć executorservice w aplikacji Android

ze swojego doświadczenia przy użyciu ExecutorService w aplikacji Android, a także biorąc pod uwagę zmiany stanu aplikacji, jeśli nie chcą ciągle zamknięcie i ponowne utworzenie executorservice w ten sposób:

executor = Executors.newCachedThreadPool(); 
    executor.submit(some Runnable); 
    executor.shutdown(); 

, o której godzinie i gdzie chciałbyś polecić zamknięcie usługi, a następnie ją przywrócić, aby zapobiec niektórym wyciekom lub niektórym nieprzewidzianym konsekwencjom?

Ja przeważnie nawiązujący do:

1) APP Zamknięcia przy tylnej przycisku na ostatniej aktywności w backstack (Aplikacja korzysta z wielu działań) 2) Zastosowanie dzieje się w tle (na każdy z tych rodzajów działalności) 3) Aplikacja z powrotem na pierwszy plan (w dowolnej z tych czynności)

+2

Ktoś, kto ma kilka dobrych wskazówek dotyczących wyłączania pojedynczej (lub zamkniętej) usługi ExecutorService, która została uruchomiona na początku aplikacji? Jeśli usługa ExecutorService nie zostanie zamknięta, nie będzie ona zbiorem śmieci, a w efekcie aplikacja nie zostanie zebrana w postaci śmieci (jeśli zadania wykonywane przez usługę executora zawierają pewne odniesienia do działania, lub inny kluczowy obiekt), nawet jeśli są zamknięte. Czy istnieje jakiś sposób łaski to zrobić? Do tej pory nazywałam shutdown za każdym razem, gdy coś przesłałem, iw efekcie odtworzyłem ExecutorService raz za razem.To nie jest dobre rozwiązanie w moich oczach ... – Lucas

Odpowiedz

8

Możesz wykonać jedną pracę. Utwórz executor jako demona. Następnie zakończy się automatycznie po wyjściu z aplikacji. Nie musisz jednoznacznie dzwonić do shutdown.

ExecutorService es = Executors.newSingleThreadExecutor(new ThreadFactory() { 
    @Override 
    public Thread newThread(Runnable r) { 
     Thread t = new Thread(r); 
     t.setDaemon(true); 
     return t; 
    } 
}); 
+0

Właściwie o tym zapomniałem, ale znalazłem tę sugestię gdzieś w związku z czymś innym i już to zaimplementowałem jakiś czas temu. Jednakże, ponieważ odpowiedziałeś, zaznaczenie jest twoje. – Lucas

3

mam singleton instancję ExecutorService który obejmuje zasięgiem Android przykład przez aplikację obiekt wykresu sztyletu. Tak więc instancja funkcjonuje tak długo, jak sam obiekt Application. Ponieważ klasa aplikacji Android nie oferuje wywołania zwrotnego onDestroy(), nigdy nie wiadomo, kiedy należy wywołać shutdown() w ExecutorService.

Ponieważ bałem się wycieków pamięci, patrzyłem również na ThreadPoolExecutor i bawiłem się nim, aby się dowiedzieć. To co znalazłem: Executors.newCachedThreadPool() tworzy ThreadPoolExecutor z następującymi parametrami:

ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()) 

To corePoolSize 0, co oznacza, że ​​minimalna liczba pracowników: 0 wątków jest utrzymywane przy życiu, tak nie ma. Kiedy TPE (a.k.a ExecutorService) wykonuje zadanie, tworzy wątek roboczy i dodaje go do puli. Teraz, gdy nie pojawia się żadne nowe zadanie w czasie 60 sekund, wątek roboczy (wciąż utrzymywany przy życiu) jest kończony i usuwany z puli (pamięci podręcznej).

Dla mnie oznacza to, że nie będzie wycieku pamięci, nawet jeśli shutdown() nigdy nie zostanie wywołany w ExecutorService, ponieważ wszystkie wątki robocze, które kiedykolwiek istnieją, przestaną działać i zostaną usunięte z puli, gdy nie będzie nowych Zadanie przychodzi w trakcie czasu oczekiwania. Sądzę, że w ten sposób nie będzie żadnych odniesień do wątków roboczych pozostawionych w puli, więc GC może oczyścić instancję TPE.

Możesz mnie poprawić, jeśli się mylę.

+1

Awsome find. Dzięki, Sebastian. Zrobiłem mały test właśnie teraz i rzeczywiście zachowuje się dokładnie tak, jak wskazałeś, i jak napisano w dokumentacji ThreadPoolExecutor. Wydaje się, że jest to drugie rozwiązanie, a bardziej preferowane, jeśli nie chcemy, aby wątki były Deamonami. Możesz także zmienić ustawienie KeepAlive, jeśli rzucisz ExecutorService na ThreadPoolExecutor. Tak więc, aby ukończyć, nie widzę niczego złego w przypadku, który zaprezentowałeś i zdecydowanie spróbuję użyć go w następnym projekcie. – Lucas