主線程中Thread.Sleep()是否會致使ANR

前言:android

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)來模擬耗時操做。
 
正文:ide

    之前個人理解就是 「在主線程作了耗時操做」就會引發ANR,如今我以爲我是錯誤的,爲何呢?
由於ANR的意思是應用沒有響應,可是耗時操做實際上 並不必定會致使沒有響應。post

我對沒有響應的理解是:測試

 有人(事件或操做)發出了一個請求,可是主線程沒有對這我的進行反饋(多是沒時間、多是不想理、多是手被綁住了沒有辦法理你),這個叫沒有響應ui

下面舉個例子來驗證下。spa

public class MainActivity extends AppCompatActivity {.net

    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;

好了,至此完結,小夥伴若是有問題請留言

相關文章
相關標籤/搜索