总结了以下六种常用的Android延时执行策略,以此记录:
1、TimerTask
2、Handler.postDelayed
3、Handler.sendEnptyMessageDelayeed
4、Thread.sleep线程休眠-需要在子线程
5、使用AlarmManager-全局定时器或者闹钟
6、Wait
首先定义一个时间常量:
public static final long DELAYTIME = 2000L;
1、TimerTask
TimerTask mTimerTask = new TimerTask() {
@Override
public void run() {
Log.e(TAG, "TimerTask -run:");
}
};
//timer可以复用,timerTask不可复用,否则闪退
if (mTimer ==null){
mTimer = new Timer();
}
mTimer.schedule(mTimerTask,DELAYTIME);
Handler.postDelayed
handler.postDelayed(new Runnable() {
@Override
public void run() {
Log.e(TAG, "handler.postDelayed :");
}
},DELAYTIME);
注意:以上用法timer可以复用,timerTask不可复用。
第二种和第三中都依赖Handler,先定义一个handler
public static class MyHandler extends Handler{
private final WeakReference<Activity> activityWeak;
public MyHandler(Activity activity){
activityWeak = new WeakReference<>(activity);
}
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
TimerActivity activity = (TimerActivity) activityWeak.get();
switch (msg.what){
case TimerActivity.MESSAGE1:
Log.e(TAG, "handleMessage: what="+msg.what );
break;
default:
Log.e(TAG, "handleMessage: default -what="+msg.what );
break;
}
}
}
2、Handler.postDelayed
handler.postDelayed(new Runnable() {
@Override
public void run() {
Log.e(TAG, "handler.postDelayed :");
}
},DELAYTIME);
3、Handler.sendEnptyMessageDelayeed
Log.e(TAG, "handler.sendEmptyMessageAtTime :start");
handler.sendEmptyMessageDelayed(MESSAGE1,DELAYTIME);
Log.e(TAG, "handler.sendEmptyMessageAtTime :");
4、Thread.sleep线程休眠-需要在子线程,sleep是线程的方法,他休眠中不会释放锁
Log.e(TAG, "Thread.sleep: onClick" );
Object lock = new Object();
new Thread() {
@Override
public void run() {
super.run();
try {
synchronized (lock){
Log.e(TAG, "Thread.sleep: 子线程start" );
Thread.sleep(20000);
Log.e(TAG, "Thread.sleep: 子线程end" );
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
try {
Log.e(TAG, "Thread.sleep: onClick-1" );
Thread.sleep(200);//此行代码影响甚大,需灵活注释,
虽然上面new Thread耗时很短,但是也是有一定开销足以让它在主线程顺序之后执行
Log.e(TAG, "Thread.sleep: 主线程执行-准备获取锁" );
synchronized (lock){
Log.e(TAG, "Thread.sleep: 主线程已获得锁" );
}
Log.e(TAG, "Thread.sleep: 主线程已释放锁锁" );
} catch (InterruptedException e) {
e.printStackTrace();
}
主线程没有200毫秒延时也就是注释Thread.sleep(200)就会先执行主线程然后进入子线程,虽然上面new Thread耗时很短,但是也是有一定开销足以让它在主线程顺序之后执行,以上代码测试发现从new Thread到子线程内第一行代码执行耗时不足1毫秒。以下是运行日志:
2023-12-11 15:12:26.944 18617-18617/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.sleep: ?onClick
2023-12-11 15:12:26.945 18617-18617/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.sleep: ?onClick-1
2023-12-11 15:12:26.945 18617-18617/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.sleep: ?主线程执行-准备获取锁
2023-12-11 15:12:26.946 18617-18617/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.sleep: ?主线程已获得锁
2023-12-11 15:12:26.946 18617-18919/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.sleep: ?子线程start
2023-12-11 15:12:46.947 18617-18919/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.sleep: ?子线程end
======================================
?主线程有200毫秒延时也就是不注释Thread.sleep(200),就会先进入子线程执行完
然后进入主线程。以下是运行日志:
2023-12-11 15:09:40.785 17990-17990/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.sleep: ?onClick
?2023-12-11 15:09:40.786 17990-17990/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.sleep: ?onClick-1
?2023-12-11 15:09:40.786 17990-18231/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.sleep: ?子线程start
?2023-12-11 15:09:40.987 17990-17990/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.sleep: ?主线程执行-准备获取锁
?2023-12-11 15:10:00.787 17990-18231/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.sleep: ?子线程end
?2023-12-11 15:10:00.787 17990-17990/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.sleep: ?主线程已获得锁
5、使用AlarmManager-全局定时器或者闹钟。适用一直在后台运行的定时任务,此处放在一个service执行:
Intent intent = new Intent();
intent.setAction("short");
ComponentName component = new ComponentName(TimerActivity.this, MyReceiver.class);
intent.setComponent(component);
//这里除了启动广播也可以换成启动Activity和service
PendingIntent sender = PendingIntent.getBroadcast(TimerActivity.this,0,intent,0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND,5);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),sender);
6、Wait-必须使用synchronized,他是Object的方法,他休眠会释放锁
Object lock = new Object();
new Thread(){
@Override
public void run() {
super.run();
try {
// synchronized (lock){ //没有synchronized锁就会报错:java.lang.IllegalMonitorStateException: object not locked by thread before wait()
Log.e(TAG, "Thread.wait: start" );
//以下两行需灵活注释
lock.wait(2000);
// Thread.sleep(2000);
Log.e(TAG, "Thread.wait: end" );
// }
} catch (Exception e) {
e.printStackTrace();
}
Log.e(TAG, "Thread.wait: 子线程第二条" );
}
}.start();
try {
Thread.sleep(200);
Log.e(TAG, "Thread.wait: 主线程开始获取锁" );
synchronized (lock){
Log.e(TAG, "Thread.wait: 主线程已获得锁" );
}
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.wait(2000)放开,Thread.sleep(2000)注释,日志如下:
2023-12-11 14:21:34.371 9385-9748/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.wait: ?start
2023-12-11 14:21:34.571 9385-9385/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.wait: ?主线程开始获取锁
2023-12-11 14:21:34.571 9385-9385/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.wait: ?主线程已获得锁
2023-12-11 14:21:36.372 9385-9748/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.wait: ?end
2023-12-11 14:21:36.372 9385-9748/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.wait: ?子线程第二条
Thread.sleep(2000)放开,lock.wait(2000)注释,日志如下:
sleep是线程的方法,他休眠中不会释放锁
2023-12-11 14:24:27.519 10346-10750/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.wait: ?start
2023-12-11 14:24:27.719 10346-10346/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.wait: ?主线程开始获取锁
2023-12-11 14:24:29.520 10346-10750/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.wait: ?end
2023-12-11 14:24:29.520 10346-10750/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.wait: ?子线程第二条
2023-12-11 14:24:29.520 10346-10346/com.example.testdemo3 E/com.example.testdemo3.activity.TimerActivity: Thread.wait: ?主线程已获得锁