android 多线程 时间不准,Android主线程进行 Thread.Sleep()会导致ANR吗

首先 先 明白一个问题:什么是ANR

Application Not Responding,意思是”应用没有响应“

以前我的理解就是 “在主线程做了耗时操作”就会引起ANR,现在我觉得我是错误的,ANR的意思是应用没有响应,耗时操作实际上 并不一定会导致没有响应,我对没有响应的理解是

有人(事件或操作)发出了一个请求,但是主线程没有对这个人进行反馈(可能是没时间、可能是不想理、可能是手被绑住了没有办法理你),这个叫没有响应

那举个例子

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

// do some blablabla...

Log.d("test", "准备sleep30秒")

Thread.sleep(30000)

Log.d("test", "sleep30秒完成")

// do some blablabla...

}

这段代码在 onCreate 中 sleep 了 30秒,会出现 ANR 吗?

答案是

可能会,也可能不会

当主线程在 Sleep 的时候,如果 UI线程不需要进行操作,也就是说没有消息会发送给UI线程并要求UI线程进行处理的时候 Sleep 30秒就不会导致ANR,因为没有 出现 ANR(应用没有响应)的情况啊,没有人向线程请求什么东西,也就不需要响应了,既然没有响应了,那怎么会有ANR呢?

但是,但线程在Sleep的时候,主线程有接收到需要处理的请求的时候

需要注意的是,需要处理的请求,不一定只是用户的手动触摸,也有可能是其他线程需要对线程进行UI更新的请求,这个时候UI线程正在Sleep,根本没有办法理你(不想理你),这就符合了ANR的条件,所以会出现ANR(比如说在这 30 秒内,点击了 返回按钮,就会出现 ANR)

另外,如果在这个30秒内进行UI更新会发生ANR吗?

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

Handler().postDelayed(Runnable {

Log.d("sleep_test", "准备更新text")

btn_test.text = "update btn text"

Log.d("sleep_test", "更新text完成")

}, 10000)

Log.d("sleep_test", "准备sleep30秒")

Thread.sleep(30000)

Log.d("sleep_test", "sleep30秒完成")

Log.d("sleep_test", "first update")

btn_test.text = "This is the first update"

}

输出结果为:

D/sleep_test: 准备sleep30秒

D/sleep_test: sleep30秒完成

D/sleep_test: first update

D/sleep_test: 准备更新text

D/sleep_test: 更新text完成

并没有发生ANR,这是因为这段代码里面的sleep休眠了线程,代码里面的更新操作根本没有在 sleep的时候被触发(处于休眠状态),也就没有了发送请求的前提条件,所以并没有发生ANR。但是如果用户手动进行了触摸操作,相当于有一个请求的事件了,而主线程又被休眠了,超过了规定的时间就会触发ANR提示

在android里面都对其进行了常量定义

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;

ContentProvider 超时

// 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;

ANR的学习目前就到这个点,后续还要继续学习

延伸:Thread.sleep() 还有其加锁的问题

由于CPU分配的每个线程的时间片极为短暂(一般为几十毫秒),所以,CPU通过不停地切换线程执行,这样就给程序员一种错觉,以为多个线程是在同时执行。sleep就是正在执行的线程主动让出CPU,CPU去执行其他线程,在sleep指定的时间过后,CPU才会回到这个线程上继续往下执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值