展开说说: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() {@Overridepublic 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() {@Overridepublic 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);}@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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(){@Overridepublic 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: 主线程已获得锁
相关文章:
展开说说:Android之常用的延时执行策略
总结了以下六种常用的Android延时执行策略,以此记录: 1、TimerTask 2、Handler.postDelayed 3、Handler.sendEnptyMessageDelayeed 4、Thread.sleep线程休眠-需要在子线程 5、使用AlarmManager-全局定时器或者闹钟 6、Wait 首先定义一个时间常量&…...
Jenkins在window下配置Android打包配置
在Windows下配置Jenkins进行Android打包的步骤如下: 安装Jenkins:从Jenkins官网下载适用于Windows的安装包,并按照安装向导的指示完成安装。 启动Jenkins服务:启动Jenkins服务,确保服务正常运行。 配置Jenkins&#…...
云原生系列2-GitLab和Jenkins
1、GitLab类似github,是个私有仓库 1、GitLab安装,至少8G内存4核cpu # 查找Gitlab镜像 docker search gitlab/gitlab-ce # gitlab镜像拉取 docker pull gitlab/gitlab-ce # 查看镜像 docker images # 本机先建3个目录,为了gitlab容器通过挂…...
xcode无线真机调试详细图文步骤
步骤一、 步骤二: 步骤三: 配置完到这里,点击真机右键,菜单栏并未出现connect via ip address 选项,也没出现无线连接的小地球图标,别慌,接着进行下一步操作即可。 步骤四: 1.打开…...
EasyExcel合并相同内容单元格及动态标题功能的实现
一、最初版本 导出的结果: 对应实体类代码: import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ContentLoopMerge; import com.al…...
【论文解读】Comparing VVC, HEVC and AV1 using Objective and Subjective Assessments
时间:2020 级别:IEEE 机构: IEEE 组织 摘要: 对3种最新的视频编码标准HEVC (High Efficiency video Coding)测试模型HM (High Efficiency video Coding)、amedia video 1 (AV1)和Versatile video Coding测试模型 (VTM)进行了客观和…...
动态窗口法Dynamic Window Approach在动态环境中避障
以这个博主的代码为基础,加了一个碰撞检测,但是这个碰撞检测目前还不完善,思路应该是这个思路,以后有时间再完善吧。 动态窗口法:【路径规划】局部路径规划算法——DWA算法(动态窗口法)|&#…...
2023.12.15 FineBI与kettle
1.结构化就是可以用schema描述的数据,就是结构化数据,能转为二维表格, 如CSV,Excel, 2.半结构化就是部分可以转换为二维表格,如JSON,XML 3.非结构化数据,就是完全无法用二维表格表示的数据,如Word文档,Mp4,图片,等文件. kettle的流程 新建转换-构建流图-配置组件-保存运行 使…...
Python tkinter 初探Toplevel控件搭建父子窗口
目录 Toplevel控件搭建父子窗口 最简明的父子窗口框架 改进一:屏蔽和开放按钮 改进二:子窗口始终在主窗口之上 改进三:增加子窗口的关闭协议 改进四:使子窗口长获焦点 总结 Toplevel控件搭建父子窗口 最近,用P…...
SpringCloud源码探析(十二)-基于SpringBoot开发自定义中间件
1.概述 中间件是一种介于操作系统和应用软件之间,为应用软件提供服务功能的软件,按功能划分有消息中间件(Kafka、RocketMQ)、通信中间件(RPC通信中间件,dubbo等),应用服务器等。中间…...
基于CNN+数据增强+残差网络Resnet50的少样本高准确度猫咪种类识别—深度学习算法应用(含全部工程源码)+数据集+模型(一)
系列文章目录 基于CNN数据增强残差网络Resnet50的少样本高准确度猫咪种类识别—深度学习算法应用(含全部工程源码)数据集模型(一) 基于CNN数据增强残差网络Resnet50的少样本高准确度猫咪种类识别—深度学习算法应用(含全部工程源码)数据集模型…...
python实现贪吃蛇游戏
文章目录 1、项目说明2、项目预览3、开发必备4、贪吃蛇代码实现4.1、窗口和基本参数实现4.2、绘制背景4.3、绘制墙壁4.4、绘制贪吃蛇4.5、绘制食物4.6、实现长度信息显示4.7、定义游戏暂停界面4.8、定义贪吃蛇死亡界面4.9、实现贪吃蛇碰撞效果4.10、实现添加食物功能4.11、实现…...
ios备忘录怎么导入华为 方法介绍
作为一个常常需要在不同设备间切换的人,我深知备忘录的重要性。那些突如其来的灵感、重要的会议提醒、甚至是生活中的琐碎小事,我们都习惯性地记录在备忘录里。但当我决定从iPhone转向华为时,一个问题困扰了我:如何将那些珍贵的备…...
electron与cesium组件入门应用功能
electron与cesium组件入门应用功能 运行应用效果图: electron应用目录,需要包括三个文件: index.html main.js package.json (一)、创建一个新项目 目录名称:project_helloWolrd (二)、生成package.json文件 npm init --yes(三&#x…...
Jenkins Docker Cloud在Linux应用开发CI中的实践
Jenkins Docker Cloud在Linux应用开发CI中的实践 背景 通过代码提交自动触发CI自动构建、编译、打包是任何软件开发组织必不可少的基建,可以最大程度保证产物的一致性,方便跨组跨部门协作,代码MR等。 Docker在流水线中越来越重要ÿ…...
502 Bad Gateway with nginx + apache + subversion + ssl
svn commit的时候返回 unexpected http status 502 bad gateway on解决方法,参考:https://stackoverflow.com/questions/2479346/502-bad-gateway-with-nginx-apache-subversion-ssl-svn-copy 在nginx中代理svn中添加 location /svn {set $fixed_dest…...
【PostgreSQL内核学习(十八)—— 存储管理(存储管理的体系结构)】
存储管理 概述存储管理器的体系结构存储管理器的主要任务读写元组过程 声明:本文的部分内容参考了他人的文章。在编写过程中,我们尊重他人的知识产权和学术成果,力求遵循合理使用原则,并在适用的情况下注明引用来源。 本文主要参考…...
Android的组件、布局学习
介绍 公司组织架构调整,项目组需要承接其他项目组的android项目,负责维护和开发新需求,故学习下基础语法和项目开发。 组件学习 Toolbarheader布局部分 就是app最顶部的部分 他的显示与否,是与F:\androidProject\android_lear…...
【离散数学】——期末刷题题库(树其一)
🎃个人专栏: 🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客 🐳Java基础:Java基础_IT闫的博客-CSDN博客 🐋c语言:c语言_IT闫的博客-CSDN博客 🐟MySQL:…...
光模块市场分析与发展趋势预测
光模块是光通信领域的重要组成部分,随着数字经济,大数据,云计算,人工智能等行业的兴起,光模块市场经历了快速发展,逐渐在数据中心、无线回传、电信传输等应用场景中得到广泛应用。本文将基于当前光模块全球…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
