http://360andev.com/sessions/100-async-task-threads-pools-and-executors/
Frome 360 AnDev conference
There are many ways to use Threads and in the multithreaded world in which we live, it can be confusing when, where, and how to use these functions correctly. Still, that assumes you know what they all mean and how to manipulate them. Novices and Experts welcome as there are many schools of thought, but we will explore them all together.
Don’t worry, we have you covered.
Animated Version : but.ly/asyncThread
2. STACY DEVINO
• Senior Android Innovator at The Home Depot Dallas
Technology Center
• Works on Consumer Mobile App and Internal
Product Innovation
• Six Sigma BlackBelt, Intel Innovator, DMS Member,
Vintage game collector/restorer
• Women Techmakers Lead for Dallas/ Ft. Worth
WEBSITES
www.stacydevino.com
www.ledgoes.com
www.openbrite.com
EMAIL
childofthehorn@gmail.com
G+
https://plus.google.com/+S
tacyDevino
TWITTER
@DoesitPew
3. Why do I need to know Multithreaded Programming?
What is it?
Basically, it allows you to
run multiple tasks
concurrently (all at the same
time) without interfering with
each other.
Important : CORE SKILL of the modern developer
4. What is a
Thread?
Thread is an independent
execution worker.
All of Android works on
Threads.
Generally, the Main Thread
is your UI Thread in
Android (ex “Hello World”
app).
Required for things such
as Login, pre-loading, and
Web/RESTful APIs
String != Bunch of Threads
5. Android has 4 basic types of Threads
Thread (Java Standard)
Handler (Android Type)
AsyncTask (Android Only)
HandlerThread (Android
Only, Handler/Looper combo)
Other stuff we will
not be going through:
Futures
IntentService
Jobs / Alarms
6. Basic Thread
What does this do?
Compute a new Random value
to be used based off of a
seed value.
How is this useful?
If you compute big Random
values on big Seeds, this
could take many processor
cycles.
long rootRandom =
System.currentMillis();
private class RandomThread
extends Thread {
long seed;
RandomThread (long seed){
this.seed = seed;
}
@Override
public void run() {
Random seededRandom =
new
Random (seed);
rootRandom =
seededRandom.nextInt();
}
}
7. Delayed Tasks
with Handler
Can be called/used
anywhere, ex. Services or
external classes
Allows direct
communication with UI/Main
Thread, good with
Messaging Tasks.
private Handler mHandler = new Handler();
private int lifeSignDelay = 5000;
private Runnable mainRunnable = new Runnable()
{
@Override
public void run() {
sendLifeSign(true);
mHandler.postDelayed(
mainRunnable, lifeSignDelay);
}
}
8. Async Task
Can ONLY be called from an
Activity (main thread,boo)
Simplified Interface for
Task based objects
Good for User Logins /
pre-loading data to be
shown on the UI
public class MyUIActivity extends AppCompatActivity {
// ……..
private ImageView = view.findViewById(R.id.someView)
// OnCreate and all other tasks contained above
//Usage
// … inside of a function or from onClick
new DownloadImageTask()
.execute("http://example.com/image.png");
//Async Task
private class DownloadImageTask extends
AsyncTask<String, Void, Bitmap> {
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
}
9. HandlerThread
(Handler + Looper)
It’s a Thread with an
Embedded Looper instance,
keeps it alive and going
handling messages/queue.
Basic
HandlerThread handlerThread = new
HandlerThread("newHandlerThread");
handlerThread.start();
Handler myHandler = new Handler(handlerThread.getLooper());
myHandler.post(new Runnable(){…});
Fancy
private void newOpenCamera() {
if (mThread == null) {
mThread = new CameraHandlerThread();
}
synchronized (mThread) {
mThread.openCamera();
}
}
private CameraHandlerThread mThread = null;
private class CameraHandlerThread extends HandlerThread {
Handler mHandler = null;
CameraHandlerThread() {
super("CameraHandlerThread");
start();
mHandler = new Handler(getLooper());
}
void openCamera() {
mHandler.post(new Runnable() {
@Override
public void run() {
oldOpenCamera();//backup
}
});
}
}
10. Lambda Expressions (only in Java 8)
private class RandomThread
extends Thread {
long seed;
RandomThread (long seed){
this.seed = seed;
}
@Override
public void run() {
Random seededRandom =
new Random
(seed);
rootRandom =
seededRandom.nextInt();
}
}
private Runnable RandomThread
= (long seed) -> {
Random seededRandom =
new Random
(seed);
rootRandom =
seededRandom.nextInt();
}
becomes
12. Self Managed
Thread
Can be Runnables or Thread
Closes itself
Can Spawn new Threads
Example shows linked
threads of a simple
Socket-level communication
app
class ConnectThread implements Runnable {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
if (newConnection) {
newConnection = false;
SocketClass.startClient();
new Thread(new TimeOutThread()).start();
}
if (serverReply != null) {
if(
serverReply.equals(Constants.ACK)
||serverReply.equals(Constants.NAK)
||serverReply.equals(Constants.STOP)
{
Thread.currentThread().interrupt();
sendCompleteEvent(serverReply);
return;
}
}
}
}
}
13. Executors
It’s Super Effective!
Executes Runnable Tasks
Asynchronous or Sequential
New Thread Spawner
(new Thread(RunnableTask)).start();
becomes
Executor executor = anExecutor();
executor.execute(new RunnableTask());
executor.execute(new NextRunnableTask());
Direct Call in Same Thread
class DirectExecutor implements Executor {
public void execute(Runnable task) {
task.run();
}
}
Asynchronous Call in new Thread
class ThreadPerTaskExecutor implements
Executor {
public void execute(Runnable task) {
new Thread(task).start();
}
}
14. ThreadPool
Executor
Executor which works with a
group of maintained “Worker”
threads.
Threads themselves do not
die, but merely transform.
Create the Pool
ThreadPoolExecutor mThreadPool =
new ThreadPoolExecutor(
// Initial processor pool size
Runtime.getRuntime().availableProcessors(),
// Max processor pool size
Runtime.getRuntime().availableProcessors(),
//Time to Keep Alive
3,
//TimeUnit for Keep Alive
TimeUnit.SECONDS,
//Queue of Runnables
mWorkQueue
);
Using the Pool
public class MyTaskManager {
//…..
// Run the Task on the Pool
mThreadPool.execute(
someTask.getRunnable());
//.. Now when done
mThreadPool.shutdown();
}
15. Executor
Services
Control of task that
provide Futures (look at
this elsewhere) in a
single Entity.
Examples:
ScheuduledExecutorService
private class NetworkService implements Runnable {
private final ServerSocket serverSocket;
private final ExecutorService pool;
public NetworkService(int port, int poolSize)
throws IOException {
serverSocket = new ServerSocket(port);
pool = Executors.newFixedThreadPool(poolSize);
}
public void run() { // run the service
try {
for (;;) {
//Run on the new ThreadPool
pool.execute(
new Handler(serverSocket.accept()));
}
} catch (IOException ex) {
//This signals shutdown the pool
pool.shutdown();
}
}
}
class Handler implements Runnable {
private final Socket socket;
Handler(Socket socket) { this.socket = socket; }
public void run() {
// read and service request on socket
}
}
* from developer.android.com
17. aka RXAndroid
Advantages:
Significantly simplifies writing of
modules as 3-4 threads can be
combined in a single Observable.
Very easy to set up communication
between multiple “Threads” or
RXJava components.
Pools and maintains worker threads.
Easy to serialize thread results
and information.
Disadvantages:
If not used properly, can have
leaked messages and observables.
(especially in the hands of those
who don’t know thread management).
It's not always as perfect in
management as a specialty built
component.
Event and Task based, so self
propagating processes are more work
to set up.
18. Other Examples of Self Managing Libs
RetroFit : Turns Restful API
calls into Java interfaces.
Handles all Thread management
and parsing. (by ReactiveX, many
contributions by Square... Lots
of Jake Wharton)
Bolts-Android : Task based model
which works on the premise of
Promises (Javascript). Allows
easy chaining of Asynchronous
tasks. (by Parse and Facebook)
Picasso : Image Loader that
uses ThreadPoolExecutor to
preload and size images. (by
Square)
Image Loader uses
ThreadPoolExecutor and Handlers
to preload and resize images.
(by Bumptech)