Async Task, Threads, Pools, and Executors
Oh My!
Stacy Devino@ 360AnDev 2016
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
WEBSITESwww.stacydevino.comwww.ledgoes.comwww.openbrite.com
G+https://plus.google.com/+StacyDevino
TWITTER@DoesitPew
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
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
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: FuturesIntentService Jobs / Alarms
Basic ThreadWhat 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(
); }
}
Delayed Tasks
with HandlerCan 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); }
}
Async TaskCan 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); } }}
HandlerThread
(Handler + Looper)
It’s a Thread with an Embedded Looper instance, keeps it alive and going handling messages/queue.
BasicHandlerThread handlerThread = new
HandlerThread("newHandlerThread");handlerThread.start();Handler myHandler = new
Handler(handlerThread.getLooper());myHandler.post(new Runnable(){…});
Fancyprivate 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 } }); } }
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
Advanced Threads and Thread Management
Self Managed Thread
Can be Runnables or ThreadCloses 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; } } } } }
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 Threadclass ThreadPerTaskExecutor implements Executor { public void execute(Runnable task) { new Thread(task).start(); } }
ThreadPoolExecutor
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();}
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
RXJava and libraries that have their ownThread Management
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.
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)
Thanks!