前言:
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;
好了,至此完结,小伙伴如果有问题请留言