When we start an App, the Android system will start a Linux Process, which contains a Thread, called UI Thread or Main Thread. Usually all components of an application run in this process. Of course, you can specify that the four major components run in different processes by modifying the android:process attribute in the code block (<activity><service><provider><receiver>) in Manifest.xml. When a component is started, if the process already exists, then the component is directly started through this process and runs in the UI Thread of this process. Many important logics are running in the UI Thread, such as system event processing, user input event processing, UI drawing, Service, Alarm, etc., as shown in the following figure: Logic contained in UI Thread The code we write is interspersed among these logics, such as detecting and responding to user touch events, processing user input, drawing custom Views, etc. If the code we insert is time-consuming, such as network requests or database reading, it will block the execution of other logic in the UI thread, causing the interface to freeze. If the freeze time exceeds 5 seconds, the system will report an ANR error. Therefore, if we want to perform time-consuming operations, we need to start another thread to execute. After the new thread finishes executing the time-consuming logic, it is often necessary to feed back the results to the interface for UI updates. Android's UI toolkit is not thread-safe and cannot update the UI in non-UI threads. All updates to the interface must be performed in the UI thread. Android provides four commonly used ways to operate multithreaded, namely: 1. Handler+Thread 2. AsyncTask 3. ThreadPoolExecutor 4. IntentService The following four methods are introduced. Handler+Thread The Android main thread contains a message queue (MessageQueue), which can store a series of Message or Runnable objects. Through a Handler, you can send Message or Runnable objects to this message queue and process these objects. Every time you create a new Handle object, it will be bound to the thread that created it (that is, the UI thread) and the message queue of the thread. From then on, the handler will start to pass Message or Runnable objects to the message queue and execute them when they are out of the queue. Handler Thread Schematic A Handler can push a Message object or a Runnable object into the message queue, and then obtain the Message or execute the Runnable object in the UI thread. There are two ways for a Handler to push a message into the message queue: Post and sendMessage: Post method: Post allows a Runnable object to be enqueued to the message queue. Its methods are: post(Runnable)/postAtTime(Runnable,long)/postDelayed(Runnable,long) For the Handler's Post method, it will pass a Runnable object to the message queue, and in this Runnable object, override the run() method. Generally, operations that need to be performed on the UI thread are written in this run() method. Handler post usage sendMessage: sendMessage allows a Message object containing message data to be pushed into the message queue. Its methods are: sendEmptyMessage(int)/sendMessage(Message)/sendMessageAtTime(Message,long)/sendMessageDelayed(Message,long) If a Handler uses sendMessage to queue a message into a message queue, it needs to pass a Message object. In the Handler, it needs to override the handleMessage() method to obtain the message passed by the worker thread. This method runs on the UI thread. Message is a final class, so it cannot be inherited. Handler definition handler sendMessage usage Pros and Cons 1. The usage of Handler is simple and clear. It can put the code of updating UI of multiple asynchronous tasks together, which is clear and concise. 2. The code for processing a single asynchronous task is slightly too much Scope of application 1. Update UI with multiple asynchronous tasks AsyncTask AsyncTask is a lightweight asynchronous class provided by Android. You can directly inherit AsyncTask, implement asynchronous operations in the class, and provide an interface to feedback the current degree of asynchronous execution (UI progress updates can be implemented through the interface), and finally feedback the execution results to the UI main thread. AsyncTask uses a blocking queue BlockingQuery<Runnable> to store tasks to be executed, and uses the static thread pool THREAD_POOL_EXECUTOR to provide a certain number of threads, 128 by default. Before Android 3.0, the parallel task executor was used by default, but after 3.0, the serial task executor was used by default. The static serial task executor SERIAL_EXECUTOR is used to control the serial execution of tasks, and tasks are taken out in a loop and assigned to threads in THREAD_POOL_EXECUTOR for execution. After one task is executed, the next one is executed. Usage examples:
Pros and Cons 1. It is simple to process a single asynchronous task and obtain the progress of the asynchronous task 2. You can cancel an AsyncTask that has not yet been completed by using the cancel method 3. The code for handling multiple asynchronous tasks is relatively large Scope of application 1. Processing of a single asynchronous task ThreadPoolExecutor ThreadPoolExecutor provides a set of thread pools that can manage multiple threads for parallel execution. This reduces the overhead of creating threads for each parallel task, and manages the common resources of multiple concurrent threads, thereby improving the efficiency of multithreading. Therefore, ThreadPoolExecutor is more suitable for the execution of a group of tasks. Executors encapsulates ThreadPoolExecutor using the factory mode, making it more convenient to use. ThreadPoolExecutor Executors provides four methods for creating ExecutorService. Their usage scenarios are as follows: 1. Executors.newCachedThreadPool() Create a fixed-length thread pool, create a thread for each task submitted, until the maximum length of the pool is reached, at which point the thread pool will keep its length unchanged 2. Executors.newFixedThreadPool() Create a cacheable thread pool. If the current thread pool length exceeds the processing needs, it can flexibly recycle idle threads and increase the number of threads when needed. It can flexibly add new threads without any restrictions on the length of the pool 3. Executors.newScheduledThreadPool() Create a fixed-length thread pool that supports scheduled and periodic task execution, similar to Timer 4. Executors.newSingleThreadExecutor() Create a single-threaded executor that only creates a single worker thread to execute tasks Scope of application 1. Batch processing tasks IntentService IntentService inherits from Service and is a lightweight packaged Service that receives and processes asynchronous requests delivered via Intent. The client starts an IntentService by calling startService(Intent), and uses a worker thread to process sequential requests in sequence, and automatically ends the Service after processing is completed. Features 1. A simple Service that can handle asynchronous tasks Original link: http://www.jianshu.com/p/2b634a7c49ec |
<<: Wang Xiao of Jiuhe Venture Capital: Is technology really just a job for the young?
>>: Top 10 basic algorithms used by programmers
Friends who love cars You often hear conversation...
This article was reviewed by Pa Li Ze, chief phys...
There is a consensus in the marketing community t...
In the education industry, the era of "let&#...
Think first: How do you measure user growth ? Wha...
...
Coffee is a symbol of refined life. The developmen...
From the time when " Xiaonei.com " bega...
Powerful smartphones hold too many secrets of thei...
There is a small bird that has its own "rice...
From Haidilao, McDonald's, to Coco, Naixue...
Many people who have just started SEM find data a...
Special thanks to Pudong Public Security Bureau a...
1. "After the COVID-19 test turns negative, ...
Place information flow ads , I examine myself thr...