Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

SMB – Procesy i wątki Michail Mokkas.

Podobne prezentacje


Prezentacja na temat: "SMB – Procesy i wątki Michail Mokkas."— Zapis prezentacji:

1 SMB – Procesy i wątki Michail Mokkas

2 W jakim celu stosujemy wielowątkowość?
Do wykonywania kilku operacji równocześnie Zamiast czekać aż pewna operacja się skończy, możemy wykonać kilka krótszych w międzyczasie. Sprawna obsługa wątków uzależniona jest od ilości rdzeni procesora. Jej brak powoduje nieresponsywność aplikacji oraz blokowanie wszystkich innych operacji do momentu ukończenia obecnie wykonującej się.

3 Main thread (UI thread)
Po odpaleniu aplikacji system Android przydziela mu nowy proces linuxowy (z jednym wątkiem zwanym „main thread”). Domyślnie każdy z komponentów aplikacji po ich uruchomieniu dodawany jest do procesu tej aplikacji i korzysta z tego samego głównego wątku. Możliwe jest uruchomienie tych komponentów (Activity, Service, Broadcast Receiver oraz Content Provider) w innym procesie poprzez plik AndroidManifest (służy do tego atrybut android:process)

4 Main thread (UI thread) kont.1
Głównie odpowiedzialny za wyświetlanie i obsługę elementów graficznych (widgetów). Dlatego nazywany jest nieraz „UI thread” Wykonywanie jakichś czasochłonnych czynności (jak np. łączność sieciowa, odpytywanie bazy danych) mogą blokować funkcjonowanie UI. Jeżeli UI będzie zablokowane przez co najmniej 5 sekund użytkownikowi pojawi się komunikat „application not responding” (ANR) z możliwością zakończenia pracy aplikacji.

5 Main thread (UI thread) kont. 2

6 Niszczenie procesów przez system
System może zadecydować o likwidacji danego procesu, jeżeli wystąpi taka potrzeba. Decyzja ta podejmowana jest według 5 poziomowej skali priorytetowej: Pierwszoplanowy proces Widoczny proces Proces wykonujący usługę (uruchomioną poprzez startService()) Niewidoczny proces Pusty proces (często używany do poprawy czasu, w jakim się ponownie odpala związany z nim element)

7 Java thread Możliwe jest użycie klasy Thread do tworzenia wątków (tak samo jak w zwykłych Javowych aplikacjach) Jeżeli skorzystamy z nich to trzeba pamiętać o dorobieniu własnych metod do: synchronizacji z „main thread” przerywania wątków zarządzania wątkami Tylko main thread ma możliwość obsługi elementów UI.

8 Java thread kont. 1 Dziedzicząc z klasy Thread:
mythread.start(); Poprzez interfejs Runnable: new Thread(myclass).start(); Jeżeli nie mamy zamiaru zmieniać zachowania klasy Thread, lepiej użyć interfejsu Runnable. public class MyThread extends Thread{ public MyThread(){ } public void run(){ //run this code } } public class MyClass implements Runnable{ public void run(){ //run this code } }

9 Worker thread Metody, które pozwalają na dostęp do wątku UI z poziomu innych wątków: void Activity.runOnUiThread(Runnable) W przypadku kiedy znajdujemy się już w UI Thread to zostanie wykonane od razu. public void activate(View v){ final String str = "State: active"; runOnUiThread(new Runnable(){ @Override public void run(){ tv.setText(str); } }); }

10 Worker thread kont. 1 boolean View.post(Runnable) – zwraca true jeżeli zdarzenie zostało dodane pomyślnie do kolejki, w przeciwnym razie false W przypadku kiedy znajdujemy się już w UI Thread to i tak zostanie dodane na koniec kolejki zdarzeń. Boolean View.postDelayed(Runnable, long) – to samo co post, ale po określonym czasie w milisekundach public void activate(View v){ final String str = "State: active"; v.post(new Runnable(){ @Override public void run(){ tv.setText(str); } }); }

11 Executor Interfejs rozdzielający zlecenie zadań od mechanizmów związanych z ich wykonywaniem. Uruchomienie z tego samego wątku: Uruchomienie w innym wątku: class SameThreadExecutor implements Executor { public void execute(Runnable r){ r.run(); } } class OtherThreadExecutor implements Executor { public void execute(Runnable r){ new Thread(r).start(); } }

12 Handler Używany do rejestrowania się do wątku w celu wymiany danych.
Powstaje kanał wymiany danych pomiędzy wątkiem, z którego Handler powstał a tym, do którego się rejestruje. Dane, które możemy przesyłać to m.in. instancje klasy Message (może zawierać nasze własne obiekty).

13 Handler kont. 1 Stworzenie w UI thread: Z poziomu innego wątku:
Handler handler = new Handler(){ @Override public void handleMessage(Message msg){ super.handleMessage(msg); } }; Message wiadomosc = new Message(); wiadomosc.obj="Something"; handler.sendMessage(wiadomosc);

14 Inne Future – interfejs, który reprezentuje rezultat zadania asynchronicznego. Posiada metody do sprawdzania, czy jakieś zadanie jest już wykonane i otrzymywania jego rezultatu. FutureTask – bazowa implementacja Future, która reprezentuje zadanie asynchroniczne. Zadanie to może być anulowane. ExecutorService – interfejs dziedziczący po Executor, który udostępnia metody do zarządzania likwidacją lub tworzącym Future do śledzenia progresu zadań asynchronicznych. ThreadPoolExecutor – implementacja ExecutorService, która wykonuje każde z zadań wykorzystując jeden z możliwych wątków z puli.

15 Elementy związane z wielowątkowością w Android
Service AsyncTask Loader

16 Service Używany do wykonywania czynności w tle.
Domyślnie Service będzie podpięty do głównego wątku aplikacji. Trzeba korzystać z mechanizmów tworzenia nowych wątków do zlecenia im zadań. Mają wyższy priorytet zachowania przez system niż activities, które nie są widoczne. Można ustawić tak, aby samoistnie zostały przywrócone do pracy po odzyskaniu potrzebnej ilości zasobów przez system. Service może uzyskać taki sam priorytet, co widoczny Activity, jeżeli ustalimy widoczną jego notyfikację (często korzystają z tego odtwarzacze muzyki).

17 Service kont. 1 Stworzenie:
Startujemy za pomocą Intent i funkcji startService(intent) public class MyService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId){ //do something return Service.START_NOT_STICKY; } @Override public IBinder onBind(Intent intent){ return null; } }

18 Service kont. 2 Zatrzymujemy Service za pomocą metody stopService()
Trzeba zadeklarować nasz Service w AndroidManifest. Do interakcji pomiędzy Activity i Service używamy metodę bindService(). Zwraca ona obiekt IBinder. W naszym przypadku jest to Null, więc komunikacja nie jest możliwa. Ustalamy także, jak nasza usługa ma się zachować po likwidacji przez system. Service.START_NOT_STICKY spowoduje, że usługa nie zrestartuje się. Jeżeli chcemy, żeby usługa była dostępna przez inne aplikacje, to powinniśmy ustawić tak, aby Service korzystał z własnego procesu.

19 Przykład bound Service
public class MyService extends Service { private final IBinder mBinder = new MyBinder(); private Date currentTime = Calendar.getInstance().getTime(); public class MyBinder extends Binder { MyService getService(){ return MyService.this; } } @Override public IBinder onBind(Intent intent){ return mBinder; } //metoda dla klienta public Date getTime(){ return currentTime; } }

20 Po stronie Activity public class MainActivity extends Activity{ private TextView tv; private MyService usluga; private boolean mBound = false; @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView)findViewById(R.id.textView); } @Override protected void onStart() { super.onStart(); Intent intent = new Intent(this, MyService.class); bindService(intent, mcon, Context.BIND_AUTO_CREATE); } @Override protected void onStop(){ super.onStop(); if(mBound){ unbindService(mcon); mBound=false; } }

21 Po stronie Activity kont. 1
public void click(View v){ tv.setText(usluga.getTime().toString()); } private ServiceConnection mcon = new ServiceConnection(){ @Override public void onServiceConnected(ComponentName className, IBinder service){ MyService.MyBinder binder = (MyService.MyBinder)service; usluga = binder.getService(); mBound = true; } @Override public void onServiceDisconneted(ComponentName arg0){ mBound = false; } }; }

22 AsyncTask Umożliwia łatwe i wygodne korzystanie z UI thread.
Zawiera metody do: tworzenia procesów działających w tle synchronizacji z main thread raportowania postępów z powrotem do UI thread Rekomendowany do krótkich zadań, które trwają zaledwie kilka sekund. Do dłuższych operacji lepiej stosować Executor, FutureTask, ThreadPoolExecutor lub inne API znajdujące się w java.util.concurrent

23 AsyncTask kont. 1 Stworzenie: (jako podklasa, np. MyActivity)
private class MyAsyncTask extends AsyncTask<String, Void, String>{ @Override protected void onPreExecute(){ } @Override protected String doInBackground(String... params){ //do stuff return null; } @Override protected void onProgressUpdate(Void... values){ } @Override protected void onPostExecute(String result){ } }

24 AsyncTask kont. 2 Aby uruchomić wystarczy: new MyAsyncTask().execute(""); Metoda execute() wykonuje doInBackground() oraz onPostExecute() doInBackground() korzysta z osobnego wątku Metody onPostExecute() oraz onProgressUpdate() wykonują polecenia w main thread Metoda publishProgress(), może być wywoływana z poziomu doInBackground() i wykonywać onProgressUpdate(). Korzysta z Java generics (<String>) oraz varargs (String… ) Niestety AsyncTask nie radzi sobie z automatu ze zmianami konfiguracji (np. po zmianie orientacji, activity się utworzy na nowo a AsyncTask będzie musiał sobie z tym poradzić poprzez dodatkowe metody programisty).

25 AsyncTask kont. 3 public class Main2Activity extends Activity { @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); new MyTask().execute("init"); } private class MyTask extends AsyncTask<String, Integer, String> { @Override protected void onPreExecute() { } @Override protected String doInBackground(String... params) { String myString = params[0]; for(int i=0; i<100; i++){ //do 100 tasks publishProgress(i); } return "result"; } @Override protected void onProgressUpdate(Integer... values) { } @Override protected void onPostExecute(String result) { super.onPostExecute(result); } } }

26 Loader Umożliwia asynchroniczne i proste ładowanie danych do activity lub fragmentów. Monitoruje źródło swoich danych i dostarcza nowych rezultatów - jak treść się zmienia. Loader jest uruchamiany na osobym wątku. Upraszcza zarządzanie wątkami poprzez wykorzystanie wywołań zwrotnych (callback).

27 Loader kont. 1 Stworzenie CursorLoader: (pomaga w asynchronicznym pobieraniu danych z bazy danych) loadInBackground() wykorzystuje osobny wątek do działania public class MyLoader extends CursorLoader { public MyLoader(Context context){ super(context); } @Override public Cursor loadInBackground(){ //zapytanie return MyDate.getItems(); } }

28 Loader kont. 2 Dodatkowo musimy umieścić metody: Wykonujemy poprzez:
onCreateLoader() onLoadFinished() onLoaderReset() Wykonujemy poprzez: getSupportLoaderManager().initLoader(LOADER_ID, null, this); Nasze activity musi implementować interfejs: LoaderManager.LoaderCallbacks<Cursor>

29 Thread-safe W niektórych przypadkach pewne metody mogą być wywoływane z kilku wątków jednocześnie. Muszą zostać stworzone w taki sposób, aby radziły sobie z tym problemem. Przykładem są metody query(), insert(), delete(), update() ContentProvidera. Możliwym rozwiązaniem jest użycie słowa „synchronized” jako parametr deklaracji metody.


Pobierz ppt "SMB – Procesy i wątki Michail Mokkas."

Podobne prezentacje


Reklamy Google