主线程中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;

好了,至此完结,小伙伴若是有问题请留言

相关文章
相关标签/搜索