博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
主线程中Thread.Sleep()是否会导致ANR
阅读量:2072 次
发布时间:2019-04-29

本文共 2832 字,大约阅读时间需要 9 分钟。

前言:

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;

   

    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() {
           
            public void onClick(View view) {
                testSleep();
            }
        });

    }

    public void testSleep() {

        //todo:10s之后本应该进行更新ui操作,但是由于此时主线程处于休眠状态,因此待主线程结束休眠之后才会进行更新ui操作

        new Handler().postDelayed(new Runnable() {

           
            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;

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

转载地址:http://ntvmf.baihongyu.com/

你可能感兴趣的文章
Linux Sed 命令
查看>>
StandardContext 错误
查看>>
如何添加网站favicon.ico图标
查看>>
cvs no such repository 问题
查看>>
MySQL中REGEXP正则表达式
查看>>
服务端UDP双向通信学习资料
查看>>
Mina TCP 编码解码相关资料收集
查看>>
Maven 打包 上传 运行
查看>>
Maven插件wagon-maven-plugin自动化部署
查看>>
使用wagon-maven-plugin插件自动部署项目
查看>>
Maven 打包的三种方式 和 Springboot 分离jar包
查看>>
ActiveMQ中Session设置的相关理解
查看>>
Linux Python 2.7.15
查看>>
Nexus配置Linux Yum Repository
查看>>
Nexus Python pip Repository
查看>>
Linux Mysql 8.0.1
查看>>
Python pymqi 连接 IBM MQ
查看>>
JVM性能调优监控工具jps、jstack、jmap、jhat、jstat、hprof 详解
查看>>
Java - JVM TLAB、对象在内存中安置顺序、垃圾收集、回收算法
查看>>
转: 关于Linux与JVM的内存关系分析
查看>>