主執行緒中Thread.Sleep()是否會導致ANR
前言:
1.對Thread.sleep(long duration)的認知。
由於CPU分配的每個執行緒的時間片極為短暫(一般為幾十毫秒),所以,CPU通過不停地切換執行緒執行,這樣就給程式設計師一種錯覺,以為多個執行緒是在同時執行。sleep就是正在執行的執行緒主動讓出CPU,CPU去執行其他執行緒,在sleep指定的時間過後,CPU才會回到這個執行緒上繼續往下執行.
2.對ANR的理解。
ANR定義:
Application Not Responding,意思是”應用沒有響應“
3.對耗時操作和Thread.sleep(long duration)的認知。
通常情況下,某些同學對耗時操作的理解就是執行了執行了一定耗時邏輯(比如,while迴圈或者進行了網路請求之類操作)。認為Thread.sleep(long duration)是讓出了當前執行緒的cpu執行權,相當於當前執行緒的休眠,所以不屬於耗時。
這樣理解比較狹隘,所謂耗時,即當前執行緒停滯不前,不在執行後面的邏輯,因此兩者都能滿足,只不過一個耗時操作把時間耗在了執行耗時邏輯,一個耗時把時間耗在了休眠上。正是基於此,所以大家才會經常使用Thread.sleep(long duration)來模擬耗時操作。
正文:
以前我的理解就是 “在主執行緒做了耗時操作”就會引起ANR,現在我覺得我是錯誤的,為什麼呢?
因為ANR的意思是應用沒有響應,但是耗時操作實際上 並不一定會導致沒有響應。
我對沒有響應的理解是:
有人(事件或操作)發出了一個請求,但是主執行緒沒有對這個人進行反饋(可能是沒時間、可能是不想理、可能是手被綁住了沒有辦法理你),這個叫沒有響應
下面舉個例子來驗證下。
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private TextView testText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
Button btnTest = findViewById(R.id.btn_test);
testText = findViewById(R.id.tv_test);
btnTest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
testSleep();
}
});
}
public void testSleep() {
//todo:10s之後本應該進行更新ui操作,但是由於此時主執行緒處於休眠狀態,因此待主執行緒結束休眠之後才會進行更新ui操作
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Log.d(TAG, "準備更新text");
testText.setText("update btn text");
Log.d(TAG, "更新text完成");
}
}, 10000);
try {
Log.d(TAG, "準備sleep30秒");
Thread.sleep(30000);
Log.d(TAG, "sleep30秒完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "first update");
testText.setText("This is the first update");
}
}
先看執行日誌:
這裡寫圖片描述
這段程式碼在 onCreate 中 sleep 了 30秒,然後更新testText,會出現 ANR 嗎?
答案是
可能會,也可能不會
不會出現ANR的情況:
如果點選了”測試按鈕“,之後的30s之內,我們沒有進行手動觸控操作(即沒有進行任何操作),則不會發生ANR,這是因為這段程式碼裡面的sleep休眠了執行緒,程式碼裡面的更新操作根本沒有在 sleep的時候被觸發(處於休眠狀態),也就沒有了傳送請求的前提條件,所以並沒有發生ANR。
會出現ANR的情況:
但是如果使用者手動進行了觸控操作(比如點選螢幕或者按返回鍵),相當於有一個請求的事件了,而主執行緒又被休眠了,超過了規定的時間就會觸發ANR提示。
如圖:
這裡寫圖片描述
好了,你現在對ANR是不是有了進一步的認識呢。
補充:
在android裡面對導致ANR的耗時時常進行了常量定義
Android N 的 ANR時間
Service 超時
// How long we wait for a service to finish executing.
static final int SERVICE_TIMEOUT = 20*1000; // 前臺
// How long we wait for a service to finish executing.
static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10; // 後臺
Broadcast 超時
// How long we allow a receiver to run before giving up on it.
static final int BROADCAST_FG_TIMEOUT = 10*1000; // 前臺
static final int BROADCAST_BG_TIMEOUT = 60*1000; // 後臺
InputDispatching 超時
// How long we wait until we timeout on key dispatching.
static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
ontentProvider 超時
// How long we wait for an attached process to publish its content providers
// before we decide it must be hung.
static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10*1000;
好了,至此完結,小夥伴如