Android開發實踐:以“專業”的態度處理多線程

來源:互聯網
上載者:User

標籤:線程   android   thread   java   退出   

   剛開始學一門程式設計語言的時候,我總是會有一種困惑,怎樣讓自己的代碼看起來更“專業”?很多時候,我們可以照著教材實現一些基本的功能,比如用Socket發送/接收幾個字元,寫一個線程完成某個非同步任務,但是在實際的項目中,往往不那麼簡單,比如需要設計Socket通訊協定,需要處理Socket的串連異常斷開,需要考慮線上程阻塞的情況下如何正常退出和釋放資源等等,關於這些“實戰經驗”,前面的文章也有所涉及,以後有空準備再開個專題跟大家分享探討一下,今天先簡單地說說怎樣更“專業”地在Android程式中處理多線程。


   下面假設實現一個簡單的定時任務,每秒鐘列印一條Log資訊,看看實現這樣一個多線程程式,有哪些需要注意的地方,關鍵點都以注釋的形式添加到代碼中了。


package com.ticktick.testthread;               import android.util.Log;                public class PrintThread implements Runnable {                         private Thread mThread;    private boolean mIsThreadStarted = false;    private volatile boolean mIsThreadExit = false; //關鍵1:定義一個volatile類型的條件變數,用於線程的退出                     public void startPrintThread() {                              if( mIsThreadStarted ) {            return;        }        mIsThreadExit = false;        mThread = new Thread(this); //關鍵2:每次啟動都重新建立新的Thread對象,因為一個Thread只能被start一次        mThread.start();             mIsThreadStarted = true;                             Log.d("PrintThread", "Timer Started");    }                     public void stopPrintThread() {                             if( !mIsThreadStarted ) {            return;        }        mIsThreadExit = true; //關鍵3:通知線程退出迴圈                             mThread.interrupt(); //關鍵4:調用interrupt,防止線程內部處於sleep或者wait等阻塞狀態                             //不過注意,對於socket.accept這樣的阻塞,thread.interrupt是沒有辦法的,但可以用socket.close來喚醒                                                try {            mThread.join(1000); //關鍵5:調用join,等待線程真正地完成退出,建議給出一個等待逾時時間        }        catch (InterruptedException e) {                 e.printStackTrace();        }                             mIsThreadStarted = false;                             Log.d("PrintThread", "Thread Stopped");    }                     public boolean isThreadStarted() {        return mIsThreadStarted;    }                     @Override    public void run() {                             Log.d("PrintThread", "Thread Run Enter !");                             while( !mIsThreadExit ) {                                     Log.d("PrintThread", "Thread Arrived !");                                     try {                Thread.sleep(1000); //關鍵6:線程迴圈中,建議使用sleep,讓其他線程可以競爭CPU,sleep(0)代表立即重新競爭一次CPU            }            catch (InterruptedException e) {                         e.printStackTrace(); //這裡可以直接跳出迴圈,也可以忽略它而再次檢查條件變數 mIsThreadExit                      }                }                             Log.d("PrintThread", "Thread Run Exit !");    }                 }


   其實,不僅是Java線程,C/C++的多線程也應該注意這幾個關鍵點,這裡再總結一下:


  (1)要定義一個volatile類型的條件變數,決定是否退出線程的死迴圈


  (2)線程迴圈中,最好有sleep延時函數,讓其他線程有機會競爭CPU


  (3)要停止線程執行,需要做三件事,1. 置位線程退出的條件變數;2. 通過類似interrupt或者socket.close 的調用,喚醒線程中的阻塞;3. 通過join函數,等待線程真正退出,然後再釋放其他相關資源


   曾經在項目中,沒有通過join等待線程退出,導致經常會在軟體退出的時候莫名其妙地crash,因此,現在格外注意這一點,而且習慣性線上程結束的地方列印出調試資訊,以保證程式中開啟的所有線程都正常地銷毀了。


   關於線程的處理就分享到這裡啦,希望對初學者有協助,有任何疑問歡迎留言或者來信[email protected]交流。


本文出自 “對影成三人” 部落格,請務必保留此出處http://ticktick.blog.51cto.com/823160/1410697

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.