zoukankan      html  css  js  c++  java
  • Android开发经验小节2:循环利用你的小对象

    在上一篇中提出的原则都是为了避免创建不必要的对象。对于占用资源较多的对象,可以在程序初始化中创建,并一直使用,比如图片资源。对于一些不变的对象,如字符串、常数,可以采用静态常量的办法。但我们开发过程中还会遇到另一种情况,有些对象虽然占用资源少,但使用频率高(比如记录屏幕点位置坐标的对象),对于这种情况应该如何处理呢?

    这个问题其实比较复杂,要具体情况具体分析,但还是有一些规律可循。

    原则1:建立对象池循环利用小对象

    例如如下类:

    1 publicclass TestPoint
    2 {
    3 publicint mX;
    4 publicint mY;
    5 public TestPoint(int x,int y)
    6 {
    7 set(x,y);
    8 }
    9
    10 publicvoid set(int x,int y)
    11 {
    12 mX=x;
    13 mY=y;
    14 }
    15 }

    使用时:

    publicvoid test()
    {
    for(int i=0;i<10000;i++)
    {
    TestPoint p
    =new TestPoint(i,i);
    。。。
    }
    }

    通过分析,以上代码会创建10000个TestPoint新对象,这当然是不合理的,可以用如下办法优化:

    1 publicclass TestPoint
    2 {
    3 publicint mX;
    4 publicint mY;
    5 public TestPoint(int x,int y)
    6 {
    7 set(x,y);
    8 }
    9
    10 publicvoid set(int x,int y)
    11 {
    12 mX=x;
    13 mY=y;
    14 }
    15
    16
    17 /**
    18 * 对象池
    19 */
    20 privatestatic ArrayList<TestPoint> sPoints=null;
    21
    22 /**
    23 * 从对象池中获取一个对象,如果空池则创建新对象,并初始化
    24 * @param x 横坐标
    25 * @param y 纵坐标
    26 * @return 对象
    27 */
    28 publicstatic TestPoint popPoint(int x,int y)
    29 {
    30 TestPoint p=null;
    31 if(sPoints!=null&& sPoints.size()>0)
    32 {
    33 p=sPoints.remove(0);
    34 p.set(x, y);
    35 }
    36 else
    37 {
    38 p=new TestPoint(x,y);
    39 }
    40 return p;
    41 }
    42
    43 /**
    44 * 向对象池归还一个对象,如果空池则先创建池
    45 * @param p 要归还的对象
    46 */
    47 publicstaticvoid pushPoint(TestPoint p)
    48 {
    49 if(sPoints==null)
    50 {
    51 sPoints=new ArrayList<TestPoint> ();
    52 }
    53
    54 sPoints.add(p);
    55 }
    56
    57 }

    在使用时:

    publicvoid test2()
    {
    for(int i=0;i<10000;i++)
    {
    TestPoint p
    =TestPoint.popPoint(i, i); //获取对象
    。。。
    TestPoint.pushPoint(p);
    //归还对象
    }
    }

    这样,由于使用过的对象归还给了对象池,当需要时优先从池中获取对象,实际创建对象的次数将明显下降。

    原则2:给你的对象池设一个上限

    前面的代码也有局限性,例如如果程序的逻辑造成其对象获取峰值较高,池中的对象将或很多,当程序对象获取需求减少时,池中的对象就成为了占用内存的累赘了。一个可行的办法是,为对象池中对象数设定一个上限,当归还对象时发现池中对象已经达到这个上限了,就不再将其放入池中。只要这个上限设定合理,池内存占用和GC释放内存压力可以找到一个较好的平衡点。

    原则3:保护好你的对象池

    这里需要强调的是,对于多线程共用的对象池,应该对所有访问对象池的静态方法进行严格的线程保护,因为ArrayList的操作还是比较费时且多线程共同对其访问是是有线程冲突的。

    小结:

    对象池的使用可以对频繁使用的小对象进行有效的循环利用,如果运用合理,可以极大地提升程序的运行效率和降低程序的资源占用。但请相信,没有普遍适用的最优方案,必须具体问题具体分析。

    作者:汪峰 www.otlive.cn

  • 相关阅读:
    xss学习笔记
    【转】Python中的正则表达式(re)
    数据隐藏技术揭秘笔记
    几道排列组合题的总结
    Notepad++来比较文件
    快捷键总结
    进制转换
    leetcode刷题(三)
    leetcode刷题(二)
    leetcode刷题(一)
  • 原文地址:https://www.cnblogs.com/otlive/p/1936181.html
Copyright © 2011-2022 走看看