android obtain,Android 模拟Message.obtain(),构建自己的缓存池
前言:
最近在做一个SDK的重构工作,app采集到信息,传递给持久化存储模块,数据存储到数据库中,上传模块定时拿取数据上传到服务器中。我负责的是数据持久化存储模块。数据持久存储这个功能简单的来说就是拿到数据后,写入到数据库中,需要的时候从数据库中提取出来就可以了。乍一看这么简单,但如果你想好好的设计一下的话,功能其实也不少。比如说:app数据传到我这个模块,模块拿到数据存储到数据库中,就是典型的生产消费者模型,感兴趣的朋友移步 LinkedBlockingQueue在生产消费者模式下的具体使用;app传递过来一个包含数据的bean类,使用完回收继续再用,类似Message.obtain()的一种缓冲池,这就是本篇文章要介绍的内容。
准备工作:
既然是参考Message.obtain()的方式构建一种缓冲池,那肯定得先阅读下Message的源码。首先Message.obtain()的构建方式:
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
代码很简单,给sPoolSync加锁后,判断sPool是否为null,不为null则将sPool引用指向一个新的Message,并将新的Message的next的引用指向sPool,随即将next置空,标记重置,sPoolSize--,返回一个Message;如果sPool为null的话,直接new出一个Message。
那么这地方就涉及到几个变量:
/*package*/ Message next;
private static final Object sPoolSync = new Object();
private static Message sPool;
private static int sPoolSize = 0;
可以看到sPoolSync就是一个锁对象,只读不写,final修饰;而
Message m = sPool;
sPool = m.next;
就是一个单链表的结构,将sPool指向当前Message,Message的next指向下一个Message。
那么回收的方法:
public void recycle() {
if (isInUse()) {
if (gCheckRecycle) {
throw new IllegalStateException("This message cannot be recycled because it "
+ "is still in use.");
}
return;
}
recycleUnchecked();
}
先是判断了isInUse()是否在使用这个Message,然后调用recycleUnchecked()回收:
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
前半段是重置各种数值,后半段是核心代码:
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
判断当前缓存池sPoolSize是否小于设定的最大缓冲池大小,如果小于这个值,则将sPool指向下一个Message,当前Message指向sPool,sPoolSize++,相当于回收了这个使用过的Message。
实践:
看懂了Message的源码,发现实现一个缓冲池也挺简单,只需要在你需要实现缓存池的类中,实现上述的复用和回收两个方法,标记一个数值,判断是否在使用,然后就可以愉快的使用缓存池了。
我们的事件类EventMessage,同Message:
private static final Object sPoolSync = new Object();//锁对象
private static EventMessage sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;//缓存池大小
private EventMessage next;
由于我们的功能比较简单,只需要一个boolean值判断有没有在使用就行了,不需要Message的flag还要判断同步异步,所以:
private boolean use;
private boolean isInUse() {
return use;
}
obtain方法:
public static EventMessage obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
LogHelper.d("缓存池取出");
EventMessage m = sPool;
sPool = m.next;
m.next = null;
m.use = false;
sPoolSize--;
LogHelper.d("缓存池取出,缓存池= " + sPoolSize);
return m;
}
}
LogHelper.d("创建新的对象,缓冲池 = " + sPoolSize);
return new EventMessage();
}
recycle方法:
/**
* 回收
*/
public void recycle() {
if (isInUse()) {
return;
}
recycleUnchecked();
}
private void recycleUnchecked() {
use = false;
resetFiled();//重置所有属性
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
LogHelper.d("回收,缓存池=" + sPoolSize);
}
}
}
然后再你需要使用这个EventMessage的时候调用下
public void setUse(boolean use) {
this.use = use;
}
在使用完这个EventMessage调用下recycle方法就可以了。
上测试结果:
1.PNG
2.PNG
多次尝试一切正常
完全ojbk
android obtain,Android 模拟Message.obtain(),构建自己的缓存池相关推荐
- android 模拟手指点击,『Android Tip』-- 模拟手势操作
平时 Android 开发中总会遇到奇葩的功能或者需求,这里做个记录和积累,以便后面开发过程中遇到类似的问题,可以快速的解决.Android tips 前言 这个版本终于快结束了,历时一个月的时间,这 ...
- Android 进阶14:源码解读 Android 消息机制( Message MessageQueue Handler Looper)
不要心急,一点一点的进步才是最靠谱的. 读完本文你将了解: 前言 Message 如何获取一个消息 Message.obtain() 消息的回收利用 MessageQueue MessageQueue ...
- android message的作用,Android消息机制之Message解析(面试)
在android的消息机制中,Message其充当着信息载体的一个角色,通俗的来说,我们看作消息机制就是个工厂的流水线,message就是流水线上的产品,messageQueue就是流水线的传送带.之 ...
- Android系统中模拟GPS位置,Android系统中模拟GPS位置
8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? Android系统中提供了模拟GPS坐标的功能,可以很方便的帮助我们测试不同地理位置下应用中各个功能效果. 模拟器中模拟 ...
- Android的消息机制: Message/MessageQueue/Handler/Looper
概览 * Message:消息.消息里面可包含简单数据.Object和Bundle,还可以包含一个Runnable(实际上可看做回调). * MessageQueue:消息队列,供Looper线程消费 ...
- 关于在用异步消息处理机制使用Message.Obtain()方法(而非New Message)获得一个Message对象的好处
类概述 定义一个包含任意类型的描述数据对象,此对象可以发送给Handler.对象包含两个额外的int字段和一个额外的对象字段,这样可以使得在很多情况下不用做分配工作. 尽管Message的构造器是公开 ...
- Android上的模拟点击
模拟点击在 Android 上有2种情况: 1,只模拟点击自己的页面: 2,只要自己进程活着,不管是哪个应用在前台,都可以模拟点击: 第一种情况比较简单: long downTime = System ...
- 【Android 安装包优化】使用 lib7zr.so 动态库处理压缩文件 ( 拷贝 lib7zr.so 动态库头文件到 Android 工程中 | 配置 CMakeLists.txt 构建脚本 )
文章目录 一.拷贝 p7zip 源码中的头文件到 Android Studio 项目中 二.配置 CMakeLists.txt 构建脚本 1.导入动态库 2.导入头文件 三.完整 CMakeLists ...
- android x86还是arm,Android x86是否模拟ARM?(Does Android x86 emulate ARM?)
Android x86是否模拟ARM?(Does Android x86 emulate ARM?) 试图找出应用程序在为ARM编译时如何在VMWare上的Android x86上工作. GUI是否在 ...
- android学习:模拟微博看看界面
这几天学会了ListView组件,这个组件真的很有用.希望在今后的开发中能大量用到. 通过ListView的学习,模拟了新浪微博的随便看看页面. 要实现的效果: 代码如下: [html] view p ...
最新文章
- React组件通信技巧
- ES 查询数据的工作原理是什么?
- Java黑皮书课后题第6章:**6.18(检测密码)一些网站对于密码具有一些规则。编写一个方法检测字符串是否是一个有效密码。编写一个程序,提示用户输入一个密码,如果符合规则,则显示…否则显示…
- php+node+redis,redis,nodejs,php,pub/sub 实战: 微信语音识别
- java的正则表达式 CPU_小心踩雷!一个小小的正则表达式竟把CPU拖垮......
- javafx弹出式窗口_JavaFX 8的弹出式编辑器
- 21秋期末考试建筑力学与结构10126k2
- 医动力Android基于CC组件化框架的探索与实践
- 由二分查找算法学习算法的时间复杂度
- python自动输入账号密码_Python如何基于selenium实现自动登录博客园
- 打球崴脚,运动崴脚怎么办?这里有一份最强处置指南
- 慕课网上的星级评分--学习视频后模仿实现
- 浅谈信息学奥赛NOIP
- detached entity passed to persist:xxx;
- oracle 如何判断当前日期是星期几
- 京东评价项目示例——在线分析及可视化
- php反序列化漏洞中当不存在__invoke时的一种利用思路
- 二维码制作方法有哪些?教你简单的二维码制作方法
- window.frames用法
- ffmpeg mkv 转 MP4