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

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

转载于:https://my.oschina.net/u/920274/blog/3062876

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值