This article is rewritten from: Android multithreading: the principle and source code analysis of AsyncTask https://www.jianshu.com/p/37502bbbb25a
Basic knowledge: see: xxxx / / you must understand the label & futuretask first
3 compound use of AsyncTask: use and Implementation (based on futuretask Implementation)
The principle of AsyncTask is that doInBackground is a new sub thread implementation. For others, such as new task, the processing result is run in the main thread
AsyncTask usage instance
AsyncTask source code analysis: process; Create a workthread inside doInBackground to execute, and post the result to the UI thread
AsyncTask is a function suite. You need to write steps, sequence and main function descriptions
- Create an instance object of WorkerRunnable class & copy the call() method
- Create an instance object of FutureTask class & copy {done()
Use: step1: to create the basic implementation of Asynctask subclass
private class MyTask extends AsyncTask<Params, Progress, Result> { .... protected void onPreExecute() {...//Actions before executing thread tasks} protected String doInBackground(String... params) { ...// Custom thread tasks Receive input parameters, perform time-consuming operations in the task, and return the results of thread task execution publishProgress(count);//publishProgress() can be called to display the progress, after which onProgressUpdate() will be executed } protected void onProgressUpdate(Integer... progresses) {...//Displays the progress of thread task execution in the main thread} protected void onPostExecute(String result) {...// UI action} protected void onCancelled() {...} }
Step 2: create an instance object of AsyncTask subclass (i.e. task instance)
MyTask mTask = new MyTask();
step3: manually call execute(Params... params)
mTask.execute();
- AsyncTask # core & common methods are as follows:
- The execution sequence of the method is as follows
Use flow chart
4. Combined use of thread pool
android thread pool is different from C + +. android thread pool uses ThreadPoolExecutor, and can only pass in runnable or callable class and its subclasses, not thread class
The use method of C + + thread pool is to directly pass in the object, and then execute the run function of the object
Executor threadPool = new ThreadPoolExecutor(...); threadPool.execute(ThreadTask); public class ThreadTask implements Runnable{ public void run() { ... // Thread execution task }
Source code analysis:
AsyncTask constructor: the callable & futuretask object is created internally
public AsyncTask() { Callable mWorker = new WorkerRunnable<Params, Result>() {...}; FutureTask mFuture = new FutureTask<Result>(mWorker) ; }
1) resolution of the callable function WorkerRunnable in the constructor: callable class (call -- > doinbackground -- > postresult -- > internalhandler (sendtotarget -- handlemessage))
- AsyncTask's constructor * / / / focuses on creating and implementing the child thread callable class: implementing time-consuming operations & sending result s to the main function interface
- The WorkerRunnable class is the constructor of callable
- Handler mechanism handler(InternalHandler) sends a message in the main thread*/
- Handler class definition and handle message*/
/*1 AsyncTask Constructor for*///Focus on the creation and implementation of sub thread callable class: realize time-consuming operation & send the result to the main function interface public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { Result result = null; try { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);//Set thread priority result = doInBackground(mParams);//Execute asynchronous operation = time-consuming operation / / that is, the time-consuming task of replication in the process } finally { postResult(result); // Send the result of the asynchronous operation to the main thread / / to update the UI } return result; } }; .....// ellipsis } //2. The workerrunnable class is the constructor of callable private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> { // Callable here is also a task; // Difference from Runnable: callable < T > has return value = its generic type Params[] mParams; }
2) The handler mechanism is encapsulated inside
/*3 handler Mechanism handler(InternalHandler) sends a message in the main thread*/ private Result postResult(Result result) { //Important: getHandler() gets the handler object Presumably, it is new InternalHandler Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result));// Create Handler object - > > from InternalHandler class - > > analysis 2 message.sendToTarget();// Send message to Handler return result; } /*4 handler Class definition and handle message mechanism*/ private static class InternalHandler extends Handler { public InternalHandler() {// Constructor super(Looper.getMainLooper());// The Looper() of the main thread is obtained / / so the instance creation & execute () of AsyncTask must be used in the main thread } public void handleMessage(Message msg) { AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj; switch (msg.what) { case MESSAGE_POST_RESULT://Pass the result to the main thread through the Handler result.mTask.finish(result.mData[0]); break; // be case MESSAGE_POST_PROGRESS://Callback onProgressUpdate() to inform the main thread of the update progress result.mTask.onProgressUpdate(result.mData); break; } } } /*Business logic implementation body */ private void finish(Result result) { if (isCancelled()) {//1. Operation when canceling a task onCancelled(result); } else { onPostExecute(result);//2 update UI operation } mStatus = Status.FINISHED;//Note: whether AsyncTask is cancelled or not, the status of AsyncTask will be changed to: FINISHED }
3) Create futuretask object
Futureask is just some exception handling;
//1 initialize FutureTask variable = 1 FutureTask - > > analysis 2 mFuture = new FutureTask<Result>(mWorker) { // Introduction to done (): the calling method after the Callable in FutureTask is executed // Function: review the call of the task and pass the result of the task not called to the UI thread through InternalHandler protected void done() { try { postResultIfNotInvoked(get());// After executing the task, check and send out the Result that has not been called } } }; /2 *FutureTask Class constructor * Definition: packaging class of 1 packaging task * Note: internal Callable<T> ,Added some status identifiers & operation Callable<T>Interface of*/ public FutureTask(Callable<V> callable) { this.callable = callable; this.state = NEW; } /*3 The result is passed to the UI thread through the InternalHandler */ private void postResultIfNotInvoked()(Result result) { final boolean wasTaskInvoked = mTaskInvoked.get();// Get task tag // If the task is not executed, the result of the task that is not called is passed to the UI thread through the InternalHandler if (!wasTaskInvoked) { postResult(result); } }
4) mTask.execute();// Source code analysis
call ladder:
AsyncTask executeOnExecutor->SerialExecutor execute(mWorker//futuretask)-->ArrayDeque.offer(runnable)-->
scheduleNext-->mTasks.poll()&THREAD_POOL_EXECUTOR.execute(futureTask)
Description: futuretask Offer (runnable) is the producer thread. Put futuretask into queue
THREAD_ POOL_ EXECUTOR. Execute (future task) is a consumer thread The thread pool executes runnable run->futureTask. run->callable. call
SerialExecutor is a queueu, and all multithreads become serial. Thread execution thread pool THREAD_POOL_EXECUTOR.
So is asynctask multi-threaded or single threaded? See the appendix for the answers
public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); } /*Parameter Description: sdefaultexecution = object of task queue thread pool class (SerialExecutor)*/ public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params) { onPreExecute();//1 main thread initialization mWorker.mParams = params;//2 add parameters to the task exec.execute(mFuture);//3. Execute a task / / exec = sdefaultexecution = the object of the task queue thread pool class (SerialExecutor) return this; } /*exec.execute(mFuture);Description: it belongs to the method of task queue thread pool class (SerialExecutor) */ private static class SerialExecutor implements Executor { // SerialExecutor = static inner class, that is, all instantiated AsyncTask objects are public // One bidirectional queue is maintained inside the SerialExecutor; The capacity is adjusted according to the number of elements final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); Runnable mActive; // execute() is decorated with synchronized lock // That is to say, the lock enables the queue to ensure that the tasks in AsyncTask are executed serially // That is, multiple tasks need to be added to the queue one by one; Then, after executing the queue header, execute the next one, and so on public synchronized void execute(final Runnable r) { mTasks.offer(new Runnable() {// Passing in the instance object of the instantiated FutureTask class is equivalent to adding a new task to the queue public void run() { try { r.run();//Focus: implement futuretask The core of run is actually callable's call time-consuming business logic } finally { scheduleNext();//Take task } } }); if (mActive == null) {// If there is no task execution at present, take one execution from the queue scheduleNext(); } } protected synchronized void scheduleNext() { if ((mActive = mTasks.poll()) != null) {// 1. Take out the queue header task THREAD_POOL_EXECUTOR.execute(mActive);// 2. Execute the extracted queue header task, that is, call the THREAD_POOL_EXECUTOR class of execution task } } }