How to properly use Android thread details _android

Source: Internet
Author: User
Tags message queue

Objective

For mobile developers, "putting time-consuming tasks into child threads to ensure the fluency of UI threads" is the first rule of threading programming, but this iron is often the main cause of the slow flow of UI threads. While we are urging ourselves to use more threads, we need to remind ourselves of how to avoid threading out of control.

One of the complex reasons for multithreaded programming is its parallel characteristics, the way the human brain works more in line with the characteristics of the single threaded serial. One subsequent task is the most comfortable state of the brain, and frequent switching between tasks creates a system anomaly such as "headaches". The multitasking of the human brain and the diversity of the multitasking performance of the computer make it easy to err when designing parallel business logic.

Another complication is the side effects of threads, including, but not limited to: Multithreading data security, deadlock, memory consumption, object lifecycle management, and the UI of the cotton. Each new thread is like a pebble thrown into the lake, creating ripples in the distance you overlook.

It is the main way for us to perceive the world with the abstraction of things. As one of the "citizens" of the operating system world, the thread is how to get the CPU and memory resources, and how to achieve maximum benefit from other "citizens"? Take these entities and behaviors like the brain, like the operating system to open the "God perspective" to correctly control the thread of this powerful beast.

Process priority (processes Priority)

Thread boarding in the process, the thread's lifecycle is directly affected by the process, and the survival of the process is directly related to its priority. When dealing with process priorities, most people intuitively know that the foreground process (foreground process) priority is higher than the background processes (Background). But this kind of rough partition can't satisfy the demand of the operating system high precision dispatch. Whether Android or iOS, the system is further refined for the foreground,background process.

Foreground Process

Foreground generally means that the user's eyes are visible, but not necessarily active . In the Android world, when an activity is in the foreground, if a user's event can be collected, input it can be judged active that if one of them pops up, it Dialog becomes a Dialog new active entity, directly facing the user. Partially obscured activity , although still visible, the state becomes inactive . It's not the right distinction visible and active It's a mistake many novice programmers make.

Background Process

The background process also has a finer division. The so-called background can be understood as invisible (invisible). For invisible tasks, Android also has a distinction of importance. An important background task is defined as Service if a process contains Service (called a service process), it is differentiated by the system in "importance" and its priority is naturally higher than Service the process not contained (called background Process), and finally there is a class of empty processes (Empty). At the beginning of the Empty process, it is difficult to understand how a process can be necessary if nothing is done. In fact, empty process is not empty, there are a lot of memory footprint.

In the world of iOS, Memory Clean Memory It is divided into and Dirty Memory , Clean Memory is the app boot is loaded into memory after the original part of the memory, usually including the initial stack, heap, text, data and so segment,Dirty Memory is due to the user's operation changed that part of the memory, that is, the app's state value. The system in the presence of low Memory warning will first clear out the dirty Memory, for users, the operation of the progress of all lost, even click the app icon again, it is all from the beginning. However, because it has Clean Memory not been purged, the IO loss from the retrieval of the app data from the disk has been avoided and the startup will be faster. This is why many people feel that the app is slow to open after the phone restarts.

The empty process in the Android World also holds app-related Clean Memory , and this part of the memory helps to boost the startup speed of apps. It is obvious that the empty process has the lowest priority.

To sum up, we can prioritize the process of the Android world into the following categories:

The priority of the process is divided into five categories from highest to lowest, the further down, the more likely to be killed by the system when the memory is tense. In short, the more easily the user perceives the process, the higher the priority must be.

Thread scheduling (Threads scheduling)

The Android system is based on a streamlined Linux kernel, and its thread scheduling is influenced by many factors, such as time slice rotation and priority control. Many beginners will assume that the time slice assigned to a thread is determined by its priority compared to other thread priorities, which is not entirely true.

The strategy used by the scheduler of the Linux system time slice when it is allocated CFS(completely fair scheduler) . This strategy will not only refer to the priority level of a single thread, it also tracks the number of times each thread has been fetched, and if the high-priority thread has been executing for a time slice long time, but the low-priority thread has been waiting, the subsequent system will guarantee that the lower-priority thread will get more CPU time. Obviously, with this scheduling strategy, high priority threads do not necessarily time slice have an absolute advantage, so the concept of Android on-line scheduling cgroups cgroups can better highlight the importance of some threads, making it easier for higher priority threads to get more time slice.

Android divides threads into multiple group categories, two of which are group especially important. One is default group that the UI threads fall into this category. The other is background group that the worker thread should belong to the class where 。background group all threads add up to only 5~10%, and all the time slice rest are allocated default group , so the design clearly guarantees the fluency of UI threads in drawing the UI.

There's a lot of people. The Android system is not as fluent as iOS because the UI thread's priority is consistent with the normal worker thread. This is actually a misunderstanding, and Android designers actually provide background group the concept of reducing the CPU consumption of working threads, but unlike iOS, Android developers need to explicitly attribute worker threads background group .

New Thread (New Runnable () {
   @Override public
   void Run () {
     process.setthreadpriority (process.thread_ Priority_background);
   }
). Start ();

So when we decide to le a thread to perform a task, we first need to ask ourselves whether the task is important at the time of completion to scramble for CPU resources with the UI thread. If not, lower the thread priority to attribute it background group to, and if so, need a further profile to see if this thread is causing the UI thread's cotton.

Although the Android system is based on a thread based unit on task scheduling, setting a single thread priority can also change the control groups distribution that it belongs to, thereby affecting CPU time slice the allocation. But the process's attribute changes also affect the scheduling of threads, and when an app goes backstage, the entire process that the app belongs to will go in to background group make sure that the foreground new process that the user sees can get as much CPU resources as possible. With ADB, you can view the current scheduling policies for different processes.

$ adb Shell Ps-p

When your app is switched back to the foreground by the user, the thread that belongs to the process will return to the original group . In the process of these users switching frequently, thread the priority will not change, but the system in time slice the distribution is constantly adjusted.

Do you really need a new thread?

The thread is not a boost to app performance, it solves the UI cotton balm. Each new thread consumes at least 64KB of memory, and the system can incur additional overhead between different threads switch context . If you open a new thread at will, it's easy to find dozens of threads running at a time at some point in the app run, as the business expands. The result is the original want to solve the UI fluency, but instead led to the occasional uncontrolled cotton.

Mobile-end app Le threads are generally designed to keep the UI fluent and increase the responsiveness of app user operations. But is it necessary to put the task in the worker thread first to understand where the bottleneck is, I/O,GPU or CPU? The appearance of the UI cotton is not necessarily a time-consuming calculation of the UI thread, possibly for other reasons, such as the layout level too deep.

Try to reuse an existing worker thread (using a thread pool) to avoid a large number of concurrently active threads, such as setting the maximum number of concurrent HTTP requests. Or put the task into a serial queue (handlerthread) sequentially, the worker thread task queue is appropriate to handle a large number of time-consuming tasks, avoiding the occurrence of a single task blocking the entire queue.

What position do you use to make a thread?

new Thread()

This is the simplest way to do the Android system, and can only be applied to the simplest scenarios, but the simple benefits are accompanied by a lot of pitfalls.

New Thread (New Runnable () {
  @Override public
  void Run () {
 
  }
}). Start ();

This approach simply started a new thread, without the concept of a task, unable to do state management. After start, the code in run is bound to be executed in the end and cannot be canceled in the middle.

Runnable as an anonymous inner class also holds a reference to the external class, which persists until the thread exits, preventing the external class object from being reclaimed by GC and causing a memory leak over time.

Without a thread-switching interface, you need to write additional thread-switching code to pass the processing results to the UI thread.

If you start from a UI thread, the thread priority defaults to, Default and is equal to, the default cgroup UI thread competing for CPU resources. This is especially important to remember in scenarios where the UI performance requirements are high

Process.setthreadpriority (Process.thread_priority_background);

Although background group the thread in the total can only win 5~10% CPU resources, but this for the vast majority of the background task processing is more than enough, 1ms and 10ms for users, are fast to imperceptible, so we generally prefer to background group perform the work thread task.

Asynctask

A typical asynctask implementation is as follows:

public class Myasynctask extends Asynctask {
 
   @Override
   protected Object doinbackground (object[] params) {
      return null;
   }
 
   @Override
   protected void OnPreExecute () {
     super.onpreexecute ();
   }
 
   @Override
   protected void OnPostExecute (Object o) {
     super.onpostexecute (o);
   }
}

Thread()In contrast to the use, there are several more API callbacks to strictly standardize the interaction between the worker thread and the UI thread. Most of our business scenarios are almost consistent with this specification, such as going to disk to read pictures, scaling processing needs to be done at the worker thread, and finally drawing to a ImageView control that needs to switch to the UI thread.

Several of the asynctask callbacks give us the opportunity to interrupt the task and be more flexible in the management of the task State Thread() . It is noteworthy that the Asynctask cancel() method does not terminate the execution of the task, and the developer needs to check cancel the status value to determine whether to abort the task.

Asynctask also has an implicit problem of holding an external class object reference, requiring special attention to prevent accidental memory leaks.

Asynctask because the serial and parallel execution behavior in different system versions is inconsistent, is criticized by many developers, this is indeed a mishap, most of the multi-threaded scenarios need to be clear whether the task is serial or parallel.

Thread priority is a background minimal impact on the execution of the UI thread.

Handlerthread

In the need for more granular control of multitasking, thread switching more frequently under the scene, Thread() and AsyncTask will appear powerless. Handlerthread is capable of these needs and even more.

Handlerthread will Handler ,,, Thread Looper MessageQueue combine several concepts. Handler is the external interface of the thread, all new message or runnable through handler post to the worker thread. Looper MessageQueue switch to the worker thread to execute the new task when it is fetched. Different post methods allow us to control the task carefully, when it is executed, and the order of execution can be controlled. The biggest advantage of Handlerthread is MessageQueue that it introduces concepts and can be used for multitasking queue management.

There is only one thread behind the Handlerthread, so the task is serially executed. The serial phase is more secure for parallelism, and there is no multithreading security problem between the tasks.

The threads generated by Handlerthread will remain alive, and Looper will continue to check in the thread MessageQueue . This is different from the fact that Thread(),AsyncTask the reuse of thread instances avoids the frequent rebuilding and destruction of threads-related objects.

HandlerThreadThread(),AsyncTaskmore code than needed, but better performance in practicality, flexibility, and security.

Threadpoolexecutor

Thread(),AsyncTaskA scenario suitable for dealing with a single task, handlerthread a scenario that is suitable for serial processing of multitasking. Threadpoolexecutor is a better choice when multitasking is needed in parallel.

public static Executor Thread_pool_executor
= new Threadpoolexecutor (core_pool_size, Maximum_pool_size, Keep_ ALIVE,
timeunit.seconds, Spoolworkqueue, sthreadfactory);

Thread pooling avoids the frequent creation and destruction of threads, and obviously performance is better, but the characteristics of thread pool concurrency are often the source of difficult illnesses, and the beginning of code demotion and runaway. Multithreading parallel to the resulting bug is often the occasional, inconvenient debugging, once the emergence will consume a lot of development energy.

ThreadPool has more flexibility than handlerthread in multitasking, but it also brings greater complexity and uncertainty.

Intentservice

I have to say that Android is very granular in API design, and the same work can be done through a variety of different classes. It's IntentService another way to open a working thread, and you can tell by name the attributes that this worker thread will carry service . and AsyncTask different, no interaction with the UI thread, and unlike Handlerthread, the worker thread will always survive. Intentservice behind there is actually a handlerthread to serial processing Message Queue , from the Intentservice onCreate method can be seen:

@Override public
void OnCreate () {
  //Todo:it would is nice to have the option to hold a partial wakelock
  /D Uring processing, and to have a static startservice (context, Intent)
  //How that would launch the service & Han D off a wakelock.
 
  Super.oncreate ();
  Handlerthread thread = new Handlerthread ("intentservice[" + Mname + "]");
  Thread.Start ();
 
  Mservicelooper = Thread.getlooper ();
  Mservicehandler = new Servicehandler (mservicelooper);
}

Only after all of the Message processing has finished, the worker thread will automatically end. So you can think IntentService of it as a combination of what you want to do with Service HandlerThread UI-independent tasks in a worker thread.

Summarize

The android thread is a variety of ways, but ultimately it is mapped to Linux under the Pthread, the business design or can not take off and thread-related basic concept category: The sequence of threads, scheduling strategy, lifecycle, serial or parallel, synchronous or asynchronous and so on. Understand the various types of API thread behavior characteristics, in the design of specific business threading model natural Familiar, threading model design to have the entire app perspective breadth, avoid each business module play each. The above is the entire content of this article, I hope that the development of Android can help you, if there are questions to welcome comments to discuss.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.