Android中的多線程的實現(xiàn)方式

不少Android初學(xué)者可能覺得,說到多線程就是Handler相關(guān)的知識。其實這種理解非常片面。本篇文章詳細(xì)總結(jié)一下android中的多線程。

多線程的幾種實現(xiàn)方式:

  1. extends Thread:
class MyFirstThread extends Thread{
        @Override
        public void run() {
            super.run();
            Log.d(TAG,"thread id + " + Thread.currentThread());
        }
    }

主線程中對其調(diào)用:

MyFirstThread t = new MyFirstThread();
t.start();
  1. implements Runnable:
class MySecondThread implements Runnable {
        @Override
        public void run() {
            Log.d("xlq111","thread id + " + Thread.currentThread());
        }
    }

主線程中對其調(diào)用時,需要將其放到Thread中:

Thread t = new Thread(new MySecondThread());
t.start();
  1. FutureTask (此方式用的較少)
Callable<String > callable = new Callable<String>() {
        @Override
        public String call() throws Exception {
            Log.d("xlq111","task thread = " + Thread.currentThread());
            return Thread.currentThread().toString();
        }
    };

FutureTask<String> task = new FutureTask<>(callable);
Thread t = new Thread(task);
t.start();
  1. AsycTask (這個很熟悉)
class MyThirdThread extends AsyncTask<URL,Integer,Long>{

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected Long doInBackground(URL... urls) {
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
        }

        @Override
        protected void onPostExecute(Long aLong) {
            super.onPostExecute(aLong);
        }
    }

調(diào)用方式:

MyThirdThread thread = new MyThirdThread();
thread.execute();
  1. 線程池(此篇先不介紹)

線程間的通信:

此時便是多線程的核心機制:Handler機制。此時幾個先介紹幾個類:
Handler:用于發(fā)送和處理Message和Runnable對象;
MessageQueue:消息隊列,用于存放通過Handler發(fā)布的消息;
Looper:用于從MessageQueue中取出消息(Message)對象,并發(fā)送給Handler處理;
Message:消息的類型,里面包含幾個實例對象

各個類之前的對應(yīng)關(guān)系:
一個Handler對應(yīng)一個Looper,一個Looper可以對應(yīng)多個Handler。
一個Looper 只擁有一個MessageQueue,所以多個Handler可以共享一個MessageQueue,從而達(dá)到消息共享的目的。

通信方式:Handler有兩種工作體系來完成子線程handler的發(fā)送
post:可以post一個Runnable對象到MessageQueue中,存在下 列幾種post方法
post(Runnable);
postDelayed(Runnable,long);
postAtTime(Runnable,long);
sendMessage:可以Send一個Message對象到MessageQueue對,存在如下方法
sendMessage(Message);
sendEmptyMessage(int);
sendMessageDelayed(Message,long);
sendMessageAtTime(Message,long);

主線程handler的接收:
復(fù)寫handleMessage方法,實現(xiàn)接收到數(shù)據(jù)之后的操作。

Handler造成的內(nèi)存溢出(OOM):

看代碼:

private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
           mTextView.setText("");
        }
    };

這種常見的Handler的創(chuàng)建過程,會有可能造成內(nèi)存溢出。原因是因為mHandler是非靜態(tài)匿名內(nèi)部類的實例,持有對外部類Activity的引用,當(dāng)Activity走OnDestroy方法時,如果此時MessageQueue中還有Message沒有處理完,Message對handler持有引用,handler對activity持有引用,導(dǎo)致Activity無法被GC回收,導(dǎo)致內(nèi)存泄漏。

正確的寫法應(yīng)該是:

private static class MyHandler extends Handler {

        private WeakReference<Context> reference;   

        public MyHandler(Context context) {
            reference = new WeakReference<>(context);//這里傳入activity的上下文
        }
        @Override
        public void handleMessage(Message msg) {
            MainActivity activity = (MainActivity) reference.get();
            if(activity != null){
                activity.mTextView.setText("");
            }
        }
    }

由于handler持有的是activity的弱引用,弱引用可以被GC回收。另外還未處理完的Message,可以在onDestroy方法中調(diào)用mHandler.removeCallbacksAndMessages(null)來將Message清空,所以以上寫法,不會造成OOM。

多說幾句:

  1. 如果要在子線程中創(chuàng)建Looper或者主線程中的Looper為空,必須使用Looper.prepare()方法來創(chuàng)建Looper;

  2. 創(chuàng)建Message時,推薦使用Message.obtain()或者Handler.obtatinMessage,因為通過這兩個方法得到的對象是從對象回收池中得到,也就是說是復(fù)用已經(jīng)處理完的Message對象,而不是重新生成一個新對象,這樣對內(nèi)存開銷較小。

就寫到這,如有遺漏或錯誤,請指出。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 進(jìn)程和線程 進(jìn)程 所有運行中的任務(wù)通常對應(yīng)一個進(jìn)程,當(dāng)一個程序進(jìn)入內(nèi)存運行時,即變成一個進(jìn)程.進(jìn)程是處于運行過程中...
    勝浩_ae28閱讀 5,258評論 0 23
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,189評論 25 708
  • 從澳洲回來,果嶺夏荷詩詞文學(xué)社的老師和朋友們要給我接風(fēng)。經(jīng)過小飛社長的預(yù)約,昨夜成行。 小飛社長說要AA制的,詩社...
    獨孤行_蒼茫閱讀 965評論 6 0
  • 此刻,我聽到大空調(diào)發(fā)出的轟轟聲,小女兒叫我喝水,喝完她蓋蓋子的咣咣聲,大女兒叫我的聲音,處理完讓她們?nèi)ニX。有她倆...
    張蕾馥閱讀 135評論 0 0
  • 姓名:朱非凡 公司:杭州美登貿(mào)易 上海361期《六項精進(jìn)》反省二組 【日精進(jìn)打卡第78天】 【知~學(xué)習(xí)】 《六項精...
    朱非凡閱讀 181評論 0 0

友情鏈接更多精彩內(nèi)容