Android concurrency

52
Android Concurrency and beyond [email protected]

Transcript of Android concurrency

Page 1: Android concurrency

Android Concurrency

and beyond

[email protected]

Page 2: Android concurrency

Why is concurrency in Android important?

• Until pretty recently, real, concurrent execution happened only on expensive server hardware

• – Android already runs on multi-core devices.

• – It will get worse: Moore's law is now about number, not speed, of CPUs

• – Android devices actually need to do multiple things at the same time: Real Time Computing

Page 3: Android concurrency
Page 4: Android concurrency

Android Puts Concurrency in your Face

• The UI is single threaded but will not tolerate long running, synchronous tasks

• IPC (Binder) calls appear on non-UI threads and you can't use the UI from a non-UI thread (a topic for another day...)

Page 5: Android concurrency

Java Concurrency Primitives

• Language level constructs – Synchronized – Thread/Runnable • Concurrency library (java.util.concurrent) – Executor/Callable/Future – Atomics • All are available in Android – Low level Java tools are really low level. If you find yourself using them you might want to review your architecture • – Android Concurrency tools are firmly based on the

concurrency library (java.util.concurrent)

Page 6: Android concurrency
Page 7: Android concurrency

Java Memory Model

Page 8: Android concurrency

Compiler Optimizations

Page 9: Android concurrency

Is Vector Really so Thread Safe?

Page 10: Android concurrency

Synchronized Collections

Page 11: Android concurrency

Concurrent Collections

• CopyOnWriteArrayList

• ConcurrentHashMap

• BlockingQueue

• Vector

• Hashtable

• Collections.synchronizedMap()

• …

Page 12: Android concurrency

Executor

• Executor

• ExecutorService

• ScheduledExecutorService

• Future

• Callable

• Executors

Page 13: Android concurrency

ExecutorService Executor

Task submission:

executorService.submit(MyTask);

executorService.invokeAll(Collection<Tasks>);

executorService.invokeAny(Collection<Tasks>);

Lifecycle management:

executorService.shutdown();

executorService.shutdownNow();

Lifecycle observation:

executorService.isShutdown();

executorService.isTerminated();

executorService.awaitTermination();

Running Shutting

Down Terminated

shutdown()

Page 14: Android concurrency

Task / Execution Environment Executor

Task: Independent unit of work executed anywhere

Runnable run()

Callable call()

Execution Environment:

Technique used to execute the task

Executor execute(Runnable)

Future future = executorService.submit(Callable);

Future isDone()

isCancelled() cancel()

Task manager/observer:

Page 15: Android concurrency

Threads on Android

UI

Android App

Linux Process

Native Threads Java Threads

BG BG BG

Page 16: Android concurrency

Android Scheduling

1. Foreground

2. Visible

3. Service

4. Background

Process level:

Android App

Page 17: Android concurrency

Android Scheduling

1. Foreground

2. Visible

3. Service

4. Background

Process level:

App A

App A

Foreground Thread Group

Background Thread Group

App B App B

> 90%

< 10%

Page 18: Android concurrency

Android Scheduling

1. Foreground

2. Visible

3. Service

4. Background

Process level:

App A

App A

Foreground Thread Group

Background Thread Group

App B App B

> 90%

< 10%

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

Page 19: Android concurrency

Activity Lifecycle

Time

Activity Component

onCreate() onDestroy() onCreate() onDestroy()

Activity Object

new() GC

Activity Object

new() GC

Page 20: Android concurrency

Activity Lifecycle

Time

Activity Component

onCreate() onDestroy() onCreate() onDestroy()

Activity Object

new()

Activity Object

new()

Start

BG

Reference

Page 21: Android concurrency

Goal

What technique shall I use for my background thread

execution?

Page 22: Android concurrency

Android Asynchronous Techniques

• HandlerThread

• AsyncTask

• Service

• IntentService

• AsyncQueryHandler

• Loader

Page 23: Android concurrency

HandlerThread

• Inherits from Thread and encapsulates a Looper-object

• Thread with a message queue and processing loop

• Handles both Message and Runnable

Running Dead t.quit() t = new HandlerThread().start();

Page 24: Android concurrency

How it works HandlerThread

Handler Thread

Create and Start

Add Process

Message Queue

1

2 3

t = new HandlerThread("BgThread"); t.start();

1 Handler h = new Handler(t.getLooper()) {

@Override

public void handleMessage(Message msg) {

//Process message

} };

2

h.sendEmptyMessage(42); 3

Page 25: Android concurrency

Handler HandlerThread

Runnable/Message submission:

Lifecycle management:

Runnable/Message removal:

removeCallbacks(Runnable);

removeMessages(Message)

post(Runnable);

postDelayed(Runnable);

postAtTime(Runnable)

postAtFrontOfQueue(Runnable);

sendMessage(Message);

sendMessageDelayed(Message);

sendMessageAtTime(Message);

sendMessageAtFrontOfQueue(Message);

Page 26: Android concurrency

AsyncTask

• Wraps Handler/Looper thread communication.

• Utilizes the Executor framework.

• Callbacks for UI operations and Background operation.

Page 27: Android concurrency

onCancelled() 4b

How it works AsyncTask

UI Thread

BG Thread

new AsyncTask.execute() 1

onPreExecute() 2

3 doInBackground()

onPostExecute() 4a

AsyncTask.cancel()

Page 28: Android concurrency

Application Global Behavior AsyncTask > Pitfalls

execute()

Queue Thread Pool

Activity

execute() Activity

execute() Service

execute() Receiver

execute() *

Page 29: Android concurrency

execute()

•Execution behavior has changed over time

AsyncTask > Pitfalls

execute() < Donut:

execute() < Honeycomb:

execute()

executeOnExecutor(Executor)

>= Honeycomb:

Page 30: Android concurrency

execute() AsyncTask > Pitfalls

<uses-sdk android:targetSdkVersion="12" />

<uses-sdk android:targetSdkVersion="13" />

“So, if I call AsyncTask.execute on Honeycomb and later my tasks will run

sequentially, right?”

“Right?!?”

“Eh, it depends…”

Page 31: Android concurrency
Page 32: Android concurrency
Page 33: Android concurrency
Page 34: Android concurrency
Page 35: Android concurrency

Possible solutions: In reverse order of appeal

• Weak Reference

• Persistent

• Cancellable

• Independent

Page 36: Android concurrency

Weak Reference

• Just make all references to the Activity weak

• Currently a “well-known” solution

• The refuge of scoundrels:

– Allows the process to continue, even when the value will be discarded

– Doesn't fix references to destroyed processes

• These are the folks who used to lazily initialize their database connections.

Page 37: Android concurrency
Page 38: Android concurrency
Page 39: Android concurrency
Page 40: Android concurrency

Independent

• What happens when firing the AT is a contract with the UI, and must complete?

• Do the simplest possible proxy to the model

• The inverse of the RESTful ContentProvider cache

Page 41: Android concurrency

Service

Time

Activity Component

onCreate() onDestroy() onCreate() onDestroy()

Service Component

BG

onCreate() onDestroy()

Page 42: Android concurrency

Intent Service

Time

IntentService Component

Intent 1 BG Intent 2 Intent 3 Intent n

stopSelf()

onCreate() onDestroy()

Page 43: Android concurrency

Good Use Cases

• Serially executed tasks decoupled from other component lifecycles.

• Off-load UI thread from BroadcastReceiver.

• REST client (ResultReceiver as callback)

IntentService

Page 44: Android concurrency

AsyncQueryHandler

• API Level 1

• Asynchronous operations on a ContentResolver

• Query

• Insert

• Delete

• Update

• Wraps a HandlerThread

Page 45: Android concurrency

How it works AsyncQueryHandler

UI Thread

BG Thread

new AsyncQueryHandler(); 1

startQuery(); startInsert(); startUpdate(); startDelete();

2

onQueryComplete(); onInsertComplete(); onUpdateComplete(); onDeleteComplete();

3

DB operations

Page 46: Android concurrency

Cons

• No cursor management

• No content observation

• No data retention on configuration changes

• Background thread can’t be forced to quit

AsyncQueryHandler

Page 47: Android concurrency

Loader

• API added in Honeycomb

• Available in compatibility package

• Load data in a background thread

• Observes data changes

• Retained on configuration changes

• Connected to the Activity and Fragment lifecycles

Page 48: Android concurrency

Basics Loader

Data Source

Loader

1 Load data in BG 2 Observe data

3 Lifecycle management 4 Retained on configuration change

Page 49: Android concurrency

Data Sources Loader

Any Data Source

Content Provider

Custom Loader

Cursor Loader

Page 50: Android concurrency

How It Works Loader

public class AndroidLoaderActivity extends ListActivity implements LoaderCallbacks<Cursor>{

SimpleCursorAdapter mAdapter;

public void onCreate(Bundle savedInstanceState) {

getLoaderManager().initLoader(0, null, this);

}

@Override

public Loader<Cursor> onCreateLoader(int id, Bundle args) {

return new CursorLoader(..., CONTENT_URI, ...);

}

@Override

public void onLoadFinished(Loader<Cursor> loader, Cursor c) {

mAdapter.swapCursor(c);

}

@Override

public void onLoaderReset(Loader<Cursor> arg0) {

mAdapter.swapCursor(null);

}

}

Page 51: Android concurrency

Used Material

• http://www.infoq.com/presentations/Concurrency-Android • http://developer.android.com/reference/android/os/Proces

s.html • http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-

133-faq.html • http://docs.oracle.com/javase/specs/jls/se7/html/jls-

17.html • https://plus.google.com/u/0/105051985738280261832/po

sts/XAZ4CeVP6DC • https://github.com/keesj/gomo/wiki/AndroidScheduling • http://stackoverflow.com/questions/7931032/android-

process-scheduling • https://www.youtube.com/watch?v=_q12gb7OwsA