Under the elaborate multi-threaded Android, learned to multi-threaded, you learned to squeeze CPU!

wedge

Socrates once said: "learned to multi-threaded, you learned to squeeze CPU, just like that thing proletarian capitalists do the same."

Multithreading is a developer of technology essential point is not easy for beginners to master a good difficulty. To design a good program, it will take a reasonable thread scheduling. Today we give elaborate under Android with multi-thread-related knowledge points, opened the multi-threaded mystery.

This article only describes the various implementations of multithreading, but more in-depth exploration of the basic principles involved, to achieve "what you see is what they have learned, what they have learned to use" effect. About delve into a variety of multi-threaded principle, we have the opportunity to put behind columns elaborate.

First, what Multithreading is? Why do I use multithreading?

1.1 The concept of threads and processes

Following the procedure described system, is the minimum unit CPU thread scheduling, while the thread is a limited system resource. Generally refers to a process of the execution unit, it means a program on the PC and a mobile device or application. A process can contain multiple threads.

Simple point to understand, a process that is a Android APP, APP there are a number of threads, meaning we multithreaded programming is to achieve "a more APP thread."

There are fine bars might ask, then I Can more than one APP process? Can a process has only one thread?

I tell you, can, can.

APP includes only single-threaded Android UI thread is able to run; more than one APP process is to be achieved, related to the implementation of Android IPC mechanism, does not elaborate here.

1.2 Why use multithreading?

Bars here might say fine, you also can run single-threaded, why should my whole multithreading?

I tell you, first sentence from the perspective of Android development is concerned, similar to a false proposition. Because Google father now imposes on the UI thread can not be time-consuming operation, you must put the child thread to go inside unless your program does not involve time-consuming operation. The reason is because the time-consuming operation on the UI thread, then, to the user interface experience is "Caton." Meanwhile, if the UI thread is blocked over a certain time will trigger ANR (Application Not Responding) errors.

From the perspective of the bottom, so that the entire multi-threaded environment may execute asynchronously, which helps prevent waste of CPU cycles to improve efficiency. In other words, multiple threads can better use of CPU resources, thereby enhancing the operational efficiency of the program.

Second, how do I multithreaded programming?

2.1 Thread class and Runnable interface

To define a thread only need to create a class that inherits from Thread, and then override the parent class method to run

  class MyThread extends Thread {
      @Override
      public void run() {
          doSomething();
      }
  }

  //在需要的时候启动线程
  new MyThread().start();

Optimize it?

We do not need to inherit the entire class Thread achieve Runnable interface just like

  class MyThread implements Runnable {
      @Override
      public void run() {
          doSomething()
      }
  }

  //启动线程
  MyThread myThread = new MyThread();
  new Thread(myThread).start();

I do not want to write a special thread class how to do? You can use an anonymous class

  new Thread(new Runnable() {
      @Override
      public void run() {
          doSomething();
      }
  }).start();

2.2 thread pool

2.2.1 The significance of the thread pool

Now I will use to create a thread Runnable interface, but also the thread pool doing? In actual fact, free to create threads operating in the actual development is extremely not recommended. Why? Because the thread is a resource, repeatedly creating and destroying threads will bring additional costs on certain properties. Compared to its thread pool mainly in the following advantages:

  • Reuse threads in the pool, avoid the thread creation and destruction brought about by the performance overhead
  • Can effectively control the maximum number of concurrent thread pool, avoid congestion due to large number of threads between each other to seize system resources resulting from
  • It can be a simple thread management, and provides a timing a specified interval, and perform other functions executed cyclically
Structure and principles 2.2.2 thread pool

A complete thread pool should have so several components

  • The core thread
  • Task Queue
  • Non-core thread

When we perform asynchronous tasks by the thread pool, in fact, it is in turn carried out the following process

  1. Check the core has reached the maximum number of threads, or create a new thread core mission is the next step
  2. Check the task queue is full, otherwise it will add the task to the task queue, then the next step is
  3. Check whether the non-core reaches a maximum number of threads, or create a new thread to perform non-core tasks, then the thread pool is already saturated, and perform saturation strategy. The default saturation strategy is to throw an exception RejectedExecutionException

Hand-rubbed to achieve a thread pool below

  //CPU核心数
  private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
  //核心线程数
  private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
  //最大线程数
  private static final int MAX_POOL_SIZE = CPU_COUNT * 2 + 1;
  //非核心线程闲置的超时时间
  private static final int KEEP_ALIVE_TIME = 1;
  //任务队列
  private static final BlockingQueue<Runnable> sPoolWorkQueue =
          new LinkedBlockingQueue<Runnable>(128);
  //线程池
  private ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
          MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, sPoolWorkQueue);

  private void fun(){
      Runnable runnable = new Runnable() {
          @Override
          public void run() {
              //子线程处理耗时操作
              doSomething();
          }
      };
      poolExecutor.execute(runnable);
  }

So we implemented a simple thread pool, the number of core threads +1 CPU, non-core thread count is the number of CPU * 2 + 1, non-core thread idle time is 1 second, the size of the task queue 128.

Thread pool as well as several specific classification and different implementations, here not elaborate.

2.3 Handler

A friend might say, you say these are multi-threaded Java stuff inside, we can not be the whole point of Android-specific? OK, now entering the professional time.

Handler is an asynchronous message processing mechanisms provided by Android, we first have to learn to use the Handler to understand the message processing under four brothers:

  • Message
  • Handler
  • MessageQueue
  • Looper

Handler can help us achieve passing messages between different threads, Message here is the message body, which is something that we want to pass.

Handler's role here is a message handler, its main role is to transmit and process messages. MessageQueue is a message queue, the message sent from Handler will be placed inside the queue, each thread will have a MessageQueue object.

Looper thread is housekeeper message queue, it runs an infinite loop, each MessageQueue found in a message, then it will remove the message sent to the Handler. Each thread can only have a Looper object.

Well, the basic principles already know, and now we rub a backhand Handler

  private static final int FLAG = 1;

  private Handler mHandler = new Handler(){
      @Override
      public void handleMessage(@NonNull Message msg) {
          if (FLAG == msg.what){
              //这里已经回到主线程了
              doSomething();
          }
      }
  };

  private void fun(){
      new Thread(new Runnable() {
          @Override
          public void run() {
              //子线程发送消息
              Message message = new Message();
              message.what = FLAG;
              mHandler.sendMessage(message);
          }
      }).start();
  }

2.4 AsyncTask

In addition to Handler, Google also provides us AsyncTask father to switch threads. AsyncTask is a lightweight asynchronous tasks it can perform background tasks in the thread pool, and then pass the progress and implementation of the final results to the main thread. From the realization of the principle is concerned, AsyncTask is once again on the package of Thread and Handle.

AsyncTask itself is an abstract generic class, there are four pro-son:

  • onPreExecute()
  • doInBackground(Params…params)
  • onProgressUpdate(Progress…values)
  • onPostExecute(Result result)

The first is the method of execution is onPreExecute () method, is located in the main thread is generally used to do some preparation.

Then perform the doInBackground () method, the thread pool is located, to perform asynchronous tasks, the params shows parameters asynchronous tasks. This method needs to return the results to the onPostExecute () method.

onProgressUpdate () method executes in the main thread, when a background task execution schedule changes this method will be called.

onPostExecute () method will be called after the last asynchronous task completed, located in the main thread, result parameter is the return value of the background tasks that doInBackground () return value.

OK, the basic principles already know, and now we have to rub a hand AsyncTask

  class DownloadTask extends AsyncTask<Void,Integer,Boolean> {

      @Override
      protected void onPreExecute() {
          //这里我们使用了一个显示进度的Dialog,具体实现不表
          progressDialog.show();
      }

      @Override
      protected Boolean doInBackground(Void... voids) {
          try {
              while (true){
                  //调用我们的doDownload下载方法,具体实现不表
                  int downloadPercent = doDownload();
                  //使用publishProgress方法来更新执行的进度
                  publishProgress(downloadPercent);
                  if (downloadPercent >= 100)
                      break;
              }
          } catch (Exception e) {
              e.printStackTrace();
          }
          return true;
      }

      @Override
      protected void onProgressUpdate(Integer... values) {
          //更新下载进度
          progressDialog.setMessage("Download "+values[0]+"%");
      }

      @Override
      protected void onPostExecute(Boolean aBoolean) {
          //下载完成
          progressDialog.dismiss();
      }
  }

Download Here we create a class that inherits from AsyncTask, there are three generic, void represents a background task does not need to pass parameters, Integer as an integer type to display the progress as a unit, Boolean Boolean type that the implementation of background tasks to feedback result.

Let us run this AsyncTask is also very simple, only need to do:

  new DownloadTask().execute();

2.5 IntentService

IntentService is a special Service, which inherited the Service and is an abstract class, we can create a subclass to use. IntentService also be used for time-consuming background tasks to perform, and it will automatically stop when the task is finished.

IntentService because it is the cause of the service, and so simple thread compared to its much higher priority, and thus less likely to be killed by the system.

IntentService internal implementation is encapsulated HandlerThread and Handler, use of the words to be followed to use the Service, will skip it here later have the opportunity to introduce the Service column inside detail.

2.6 RxJava

There are fine bars might say, you speak of these methods, than a longer, than a complex, it is not the whole simple and rough stuff?

This time it needs to reposition itself in the magic weapon RxJava.

2.6.1 RxJava is a what?

In fact RxJava on the network, such as how-to articles and more river carp, too much depth here do not intend to introduce. RxJava is a reactive programming, you can not understand, then be understood as more brutal elegant multithreading can be.

2.6.2 that how to operate RxJava?

RxJava upper hand rub a common implementation

  private void fun(){
      Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {
          @Override
          public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
              emitter.onNext(1);
          }
      });

      observable.subscribeOn(Schedulers.io())     //表示在io线程执行订阅
              .observeOn(AndroidSchedulers.mainThread())  //表示在主线程接收订阅
              .subscribe(new Observer<Integer>() {
                  @Override
                  public void onSubscribe(Disposable d) {
                      //接收订阅之前调用
                  }

                  @Override
                  public void onNext(Integer integer) {
                      //接收订阅成功调用
                      doSomething();
                  }

                  @Override
                  public void onError(Throwable e) {
                      //接收订阅出错调用
                  }

                  @Override
                  public void onComplete() {
                      //接收订阅完成调用
                  }
              });
  }

emmmmm looks like quite complex, ah, can no longer simply the whole point?

OK, the call plus lambda chain arrangements

  private void fun() {
      Observable.create(emitter -> emitter.onNext(1))
              .subscribeOn(Schedulers.io())
              .observeOn(AndroidSchedulers.mainThread())
              .subscribe(integer -> {
                  //接收订阅成功
                  doSomething();
              }, throwable -> {});
  }

Ah ... there is a smell inside.

This string of code we sent a data type Integer;

subscribeOn () specifies the thread we send is io thread in the background, it can be understood as a sub-thread;

observeOn we receive specified thread main thread;

subscribe to receive messages only successful, equivalent to the above OnNext () method, essentially we are here to create a Comsumer object to receiving;

throwable call when reception fails, the above corresponds to the onError () method.

RxJava as many as dozens of operators, can achieve a variety of different flexible use of asynchronous task, there is no longer space to spend a lot of details, interested friends can go see ReactiveX Chinese documents

2.7 RxKotlin

RxKotlin RxJava can be understood as a variant on the Kotlin, the principle is the same, but the operation turned into a Kotlin language, and makes it possible to package a bit more elegant to call, here to give you a specific implementation case, not too much explain.

  private fun test() {
      Observable.create<Int> { 1 }
              .subscribeOn(Schedulers.io())
              .observeOn(AndroidSchedulers.mainThread())
              .subscribeBy(
                      onNext = {},
                      onError = {}
              )
  }

2.8 Kotlin coroutine

Coroutine actually mentioned above and the thread is not a concept, what coroutines that? According to the official description of the document, the coroutine is essentially lightweight threads. Since it is lightweight, it terms of resource consumption and performance specifications such as coroutines and threads than it should have an advantage. It would appear that we used to use asynchronous features to achieve multi-threading, and now basically can be used to replace the coroutine.

Coroutine is a new thing, do not start here between space explained, would later write a special article describes coroutines.

Third, the summary

Today summarizes several ways to achieve multi-threaded on the Android platform, I hope to give to a friend in need some help.

I enclose my Android core technology learning syllabus, access to relevant content to play with my GitHub: https://github.com/Meng997998/AndroidJX
VX: xx1341452

For advanced this way, the learning will pay off!

You take your time to invest in learning, it means that you can gain skills, have the opportunity to increase revenue.

Here to share my Android PDF Daquan learn to learn, learn this Android PDF Daquan really contain all aspects, and contains basic Java knowledge, the basis of Android, Android Advanced extension, and so on collection algorithm

My collection this study, can effectively help you grasp the knowledge points.

In short we are also here to help enhance learning advanced, but also saves you the time to learn online search data can also be shared with close friends studying together

Access: concern I see personal introduction, or direct click me free to receive

Published 168 original articles · won praise 71 · views 20000 +

Guess you like

Origin blog.csdn.net/Aerfa789/article/details/104932633