Message享元模式学习

13 篇文章 0 订阅
7 篇文章 0 订阅

java的类是由成员变量+构造函数+成员方法组成->先看成员变量

涉及复用的关键成员变量有:
Message next;
private static Message sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;

一开始的获取Message对象

    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();
    }

synchronized :这个就不在这里解释了,太基础,有兴趣的同学可以看下我之前写的并发编程里面有对应的解释。
if (sPool != null):这个判断第一次肯定是进不去的,全局搜索了一下,只有在回收的地方有赋值,所以它一直是null,那么开始的时候肯定都是直接new的方法去创建的,而且在实际过程中,可能一开始就new了很多个对象出来,因为message要等用完才会开始回收,所以一开始获取的Message都是直接new。

如何回收

    public void recycle() {
        if (isInUse()) {
            if (gCheckRecycle) {
                throw new IllegalStateException("This message cannot be recycled because it "
                        + "is still in use.");
            }
            return;
        }
        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 = UID_NONE;
        workSourceUid = UID_NONE;
        when = 0;
        target = null;
        callback = null;
        data = null;
		//上面的都是一些变量的复位,没什么好说的,关键是下面。
        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
    }

第一次进来

if (sPoolSize < MAX_POOL_SIZE) :只要复用池里面的对象还没满,就可以往里面继续加,因为我们是强引用持有,回收不了的,所以定义的最大数量要合适,这里系统定义的是最大值是50
next = sPool :第一次进来两个都是null
sPool = this :给sPool赋值,第一个用完的对象进行强应用持有,不会被回收。
sPoolSize++:统计上+1
在这里插入图片描述

第二次进来

next = sPool :sPool是上一个回收对象message1,赋值给next,注意sPool是静态。
sPool = this :给sPool赋值,第二个用完的对象进行强应用持有,不会被回收。
sPoolSize++:统计上+1,注意sPoolSize是静态。
在这里插入图片描述

第三次进来

next = sPool :sPool是上一个回收对象message2,赋值给next
sPool = this :给sPool赋值,第三个用完的对象进行强应用持有,不会被回收。
sPoolSize++:统计上+1

到了此刻,这个链表的结构应该在你的脑海中能够想象出来了。

回过头来我们再看获取message

 if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }

当复用池中存在对象的时候,sPool不为空,该判断可以进去。
Message m = sPool; //创建了一个局部对象m并赋值,可以想象成上面的message3
sPool = m.next;//把m的next对象从原来的指向message2指向自己,也就是message3
m.next = null;//把message3指向自己message3的强引用断开
m.flags = 0; // clear in-use flag ,是一个标志位,是否在使用中。
sPoolSize–;//计数减1
return m //把m对象返回给使用者使用。
经过上面的代码之后,message3指向message2的强引用没有了,对象又重新进行了使用,计数器减1.

到了这里想必大家都明白它的核心是什么了吧?

我一开始没注意直接看了复用和回收的方法,怎么都想不明白,然后第二天上班突然看到了:
private static Message sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;
就一个关键:static
好了,到了这里message的复用逻辑已经很清晰明确了,如果大家有什么问题,欢迎在评论区留言讨论。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值