您好,登錄后才能下訂單哦!
剛開始學一門編程語言的時候,我總是會有一種困惑,怎樣讓自己的代碼看起來更“專業”?很多時候,我們可以照著教材實現一些基本的功能,比如用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,因此,現在格外注意這一點,而且習慣性在線程結束的地方打印出調試信息,以保證程序中開啟的所有線程都正常地銷毀了。
關于線程的處理就分享到這里啦,希望對初學者有幫助,有任何疑問歡迎留言或者來信lujun.hust@gmail.com交流。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。