Android AsyncTask Internal Thread Pool asynchronous execution task mechanism brief analysis, androidasynctask
The source code of AsyncTask for API 25 is analyzed as follows:
If you use AsyncTask to call the execute method, the task is executed synchronously. If you want to execute the task asynchronously, you can directly call the executeOnExecutor method. In most cases, we will use the static thread pool in AsyncTask,
THREAD_POOL_EXECUTOR. This is not to analyze the internal process of AsyncTask, but to briefly introduce the workflow of the thread pool. The configuration of THREAD_POOL_EXECUTOR is as follows:
New ThreadPoolExecutor (CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit. SECONDS, sPoolWorkQueue, sThreadFactory );
This section briefly describes several parameters of ThreadPoolExecutor:
Int corePoolSize, number of core threads, which can survive in the thread pool until allowCoreThreadTimeOut is set to allow the core thread to time out. Int maximumPoolSize, the maximum number of threads allowed in the thread pool. Long keepAliveTime: when the number of threads in the thread pool exceeds the number of core threads, the non-core threads are waiting for the keepAliveTime to terminate. That is, the non-core threads are waiting for the task (survival time) for the timeout time to keepAliveTime, timeUnit, unit of timeout, BlockingQueue <Runnable> workQueue, buffer task queue, ThreadFactory threadFactory is used to create a new thread, and thread priority can be set. For more information, see the API documentation or the source code of java. util. concurrent. ThreadPoolExecutor.
Specifically, when a task is submitted to the thread pool, the system first checks whether all the tasks in the Core Thread are being executed. If the Core Thread is idle, the Core Thread executes the task, otherwise, the task is added to the Buffer Queue. After the Core Thread completes the task, the task in the buffer queue is executed. If a large number of tasks are added, the Buffer Queue is full, and tasks are submitted, non-core threads will be started to execute tasks. If the number of non-core threads is also working, that is to say, when the number of threads in the thread pool reaches the maximum number of threads MAXIMUM_POOL_SIZE, and then submit the task to the thread pool, an exception will be reported to reject the execution of the task. java. util. concurrent. rejectedExecutionException
You can use the following code to perform a simple test:
First define an AsyncTask
static int index = 1;
static class MyAsyncTask extends AsyncTask<Void, Void, Void> { @Override protected Void doInBackground(Void... params) { SystemClock.sleep(2000); return null; } @Override protected void onPostExecute(Void aVoid) { Log.d(this.getClass().getSimpleName(), "task#" + index + " had executed."); index++; } }
Here, in order to see the process described above, let the thread sleep for 2 seconds in doInbackground and output the completed log for each AsyncTask. The index ID is the number.
Then submit the task to the thread pool.
int CPU_COUNT = Runtime.getRuntime().availableProcessors(); int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4)); int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; int taskMaxCounts = MAXIMUM_POOL_SIZE + 128; for (int i = 0 ; i < taskMaxCounts; i++ ) { new MyAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void)null); }
The maximum number of tasks that can be simultaneously accommodated is MAXIMUM_POOL_SIZE + 128 (number of buffered queue tasks). For API25, how is the CPU Core 4, the maximum number of tasks is 4*2 + 1 + 128 = 137.
When all tasks in the thread pool are being executed and the Buffer Queue is full, an exception is reported when you continue to submit tasks to the thread pool. Here, you can change taskMaxCounts to MAXIMUM_POOL_SIZE + 129,
If you run the program again, the exception log is displayed.
FATAL EXCEPTION: main Process: com.aquarius.test, PID: 22425 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.aquarius.test/com.http.study.demo.VolleyActivity}: java.util.concurrent.RejectedExecutionException: Task android.os.AsyncTask$3@75bef95 rejected from java.util.concurrent.ThreadPoolExecutor@76298aa[Running, pool size = 9, active threads = 9, queued tasks = 128, completed tasks = 0] at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2449) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2509) at android.app.ActivityThread.access$1000(ActivityThread.java:153) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1373) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:5524) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:740) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:630) Caused by: java.util.concurrent.RejectedExecutionException: Task android.os.AsyncTask$3@75bef95 rejected from java.util.concurrent.ThreadPoolExecutor@76298aa[Running, pool size = 9, active threads = 9, queued tasks = 128, completed tasks = 0] at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2014) at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:794) at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1340) at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:607)