Android多線程介紹


點擊上方 藍字 關注我,❤web


前言

今天分享的面試題/知識點是:面試

Android中多線程如何實現?有哪些方式?該怎麼選擇?微信

多線程操做方法

Android中,主要提供瞭如下幾種多線程操做方法:多線程

  • Thread,Runnable
  • HandlerThread
  • AsyncTask
  • Executor
  • IntentService

Thread,Runnable

首先介紹Android中建立線程最基本的兩種方法,用到了Thread類和Runnable接口,直接上代碼異步

    /**
     * 繼承Thread
     */

    public class NewThread extends Thread{
        @Override
        public void run() {
            super.run();
        }
    }

    /**
     * 實現Runnable接口
     */

    public class NewThread2 implements Runnable{
        @Override
        public void run() {

        }
    }

這裏也沒有什麼更多的說的,都是線程最基礎的用法,通常用於界面上比較簡單的快捷用法。在Android中通常跟Handler一塊兒使用,用於線程中的通訊。編輯器

Android中爲了方便這種通訊方式,就生成了一個HandlerThread類,將Thread和Handler結合起來方便了使用。下面咱們來看看HandlerThread。ide

HandlerThread

HandlerThread的本質實際上是繼承自Thread類,而且對Thread類進行了一個封裝。主要解決的問題是,在一個已經運行的線程中去執行一些任務。oop

官方解釋是:學習

  • A Thread that has a Looper. The Looper can then be used to create Handlers.

咱們先看看使用代碼吧:flex

        HandlerThread mHandlerThread=new HandlerThread("");
        mHandlerThread.start();

        Handler mHandler =new Handler(mHandlerThread.getLooper()){
            @Override
            public void handleMessage(@NonNull Message msg) {
                super.handleMessage(msg);
            }
        };

        mHandler.sendEmptyMessage(0);

代碼很清楚表示了,HandlerThread在運行中,能夠經過handler進行一些任務處理。

它的原理其實就是在HandlerThread線程內部有一個Looper變量,進行loop()的死循環,而後經過MessageQueue進行一系列任務的排隊和處理。

那有人就會問了,這不就是普通的Thread+Looper+Handler嗎,其實差不太多,HandlerThread就至關於系統幫你封裝了一個帶looper對象的線程,不須要你本身去手動操做Looper

那麼這個HandlerThread到底有什麼實際應用呢?通常用於Android中須要新建子線程進行多個任務處理,而且須要和主線程通訊。後面要說的IntentService 內部其實就是用了HandlerThread實現的。(其實我在實際項目中用的不多,通常用Executors.newSingleThreadExecutor()方法代替,同樣的線程中管理任務隊列,後面會詳細說到線程池)

AsyncTask

AsyncTask 是一種輕量級的異步任務類,能夠在線程池中執行後臺任務,而後把執行的進度和最終結果傳遞給主線程用於更新UI。

剛纔說到若是須要新建線程進行多個任務處理而且完成和主線程通訊,就能夠用到HandlerThread(或者Executors.newSingleThreadExecutor()),那麼若是是單一任務呢,簡單的任務呢?

好比我就須要請求一個接口,而後進行UI更新,那麼就能夠用到AsyncTask,它的優勢在於簡單快捷,過程可控。見示例:

new AsyncTask<Void, Void, String>() {

    @Override
    protected void onPreExecute() {
        //請求接口以前,初始化操做
        super.onPreExecute();
    }

    @Override
    protected String doInBackground(Void... parameters) {
        //請求接口
        return "";
    }

    @Override
    protected void onProgressUpdate(Void... values) {
        //在主線程顯示線程任務執行的進度
        super.onProgressUpdate(values);
    }

    @Override
    protected void onPostExecute(String responseString) {
        //接收線程任務執行結果
    }
}.execute();

Executor

Executor類提供了一組線程池,能夠管理多個線程並行執行,線程池的優勢就在於能夠線程複用,而且合理管理全部線程。

這裏主要講三種建立線程池的方法:

        //固定大小的線程池
        ExecutorService pool = Executors.newFixedThreadPool(10);
        //不限制線程上限的線程池
        ExecutorService pool2 = Executors.newCachedThreadPool();
        //只有一個線程的線程池
        ExecutorService pool3 = Executors.newSingleThreadExecutor();

剛纔說過newSingleThreadExecutor能夠代替HandlerThread,這是由於他也是能夠串行執行全部任務,一個線程結束,下面一個線程代替並執行。至於和主線程通訊,仍是能夠用handler或者其餘常規的通訊方式。

具體的關於線程池的內容呢,你們能夠點擊查看以前的一篇專門說線程池的文章—《線程池三問》。

IntentService

IntentService 是一個繼承自Service,自帶工做線程,而且線程任務結束後自動銷燬的一個類。Service是啥?四大組件之一,能夠統一管理後臺任務,運行在前臺,能夠獲取到上下文。

而IntentService一樣具備這些特性,而且能夠在新線程管理任務,工做執行完自動銷燬。就線程池來講區別就在與IntentService擁有Service的特性,因此在須要用到上下文的時候就能夠選擇IntentService。

這裏能夠直接看看IntentService源碼:

  @Override
    public void onCreate() {
     super.onCreate();
     //建立新線程並start
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();
        mServiceLooper = thread.getLooper();
        //建立新線程對應的handler
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }
    
    @Override
    public void onStart(@Nullable Intent intent, int startId) {
      //service啓動後發送消息給handler
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }
    
    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }
        @Override
        public void handleMessage(Message msg) {
          //handler收到消息後調用onHandleIntent方法
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }

代碼很簡單,其實就是開了一個線程,經過handler,執行onHandleIntent方法。

五種方式,怎麼選擇呢?

個人建議是:

  • 輕量級,簡單的任務能夠直接用 AsyncTask
  • 須要後臺管理,用到上下文的時候用IntentService
  • 其他場景都用線程池,畢竟線程池是最推薦,最優化的線程管理方法




感謝你們的閱讀,有一塊兒學習的小夥伴能夠關注下公衆號—碼上積木❤️❤️
每日三問知識點/面試題,聚沙成塔。

天天一見

給你力量

碼上積木





點點在看,你最好看


本文分享自微信公衆號 - 碼上積木(Lzjimu)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索