展开说说:Android之常用的延时执行策略

总结了以下六种常用的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: 主线程已获得锁

相关推荐
松仔log9 小时前
Java中级——组合和继承
android·java·开发语言
我命由我1234512 小时前
Jetpack Compose - MaterialExpressiveTheme 与 MaterialTheme、ColorScheme
android·java·开发语言·java-ee·kotlin·android jetpack·android runtime
lilian23313 小时前
Harmony os 技术实战|拼豆制图06:收藏 ID、生成记录与重启恢复怎么不打架
android·java·数据库·harmonyos
2601_9557596213 小时前
ClaudeAPI成本中心与业务标签设计指南
android·java·数据库
余衫马13 小时前
2026最新版!Android Studio 极速安装与配置指南
android·ide·android studio
AFinalStone13 小时前
Android 7系统异常问题排查(五)Framework层(下)—System Server崩溃
android·tombstone·系统异常
AFinalStone13 小时前
Android 7系统异常问题排查(八)系统追踪—Trace机制与性能诊断
android·系统异常
极客猴子17 小时前
Android录音转写频繁卡顿?多款APP长时间会议场景稳定性实测
android·人工智能·智能手机·飞书
Kapaseker17 小时前
Boolean 变量到底该怎么命名?
android·kotlin
AFinalStone17 小时前
Android 7系统异常问题排查(六)应用异常(上)—ANR机制全解
android·系统异常