采用池化的思想替换StringBuffer的使用

    大家对StringBuffer的第一个印象就是,用stringbuffer.append(xxxx)替换string+=xxx会更高效。

   

        String str = "";
        str += "xxx";//new多了一个String对象
        
        
        StringBuffer sbf = new StringBuffer();
        sbf.append("xxx");//原来的StringBuffer对象
    OK,我们接下来看一下append的实现,该方法由StringBuffer的父类AbstractStringBuilder实现。

 public AbstractStringBuilder append(String str) {
        if (str == null) str = "null";
        int len = str.length();
        ensureCapacityInternal(count + len);//关键1
        str.getChars(0, len, value, count);//关键2
        count += len;
        return this;
    }
    我们看到append代码最关键的其实只是两句话,分别是上面的关键1
   /**
     * This method has the same contract as ensureCapacity, but is
     * never synchronized.
     */
    private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0)
            expandCapacity(minimumCapacity);
    }

    /**
     * This implements the expansion semantics of ensureCapacity with no
     * size check or synchronization.
     */
    void expandCapacity(int minimumCapacity) {http://product.suning.com/106010784.html#unknown
        int newCapacity = value.length * 2 + 2;
        if (newCapacity - minimumCapacity < 0)
            newCapacity = minimumCapacity;
        if (newCapacity < 0) {
            if (minimumCapacity < 0) // overflow
                throw new OutOfMemoryError();
            newCapacity = Integer.MAX_VALUE;
        }
        value = Arrays.copyOf(value, newCapacity);
    }

     关键1的代码很多,但是我们可以看到,其实很简单,就是value作为一个char数组,然后每次有新的内容加入就检测char数组value的长度是否足够,不够的话就按照一定的策略进行扩充(具体的可以参考ArrayList和HashMap的代码)。

     由这里,我们可以知道,因为每次append都是追加到value这个数组,而不是重新初始化对象,所以,和+=string这种形式的通过new String的追加是不同的。从StringBuffer这个名字,我们也可以看出,是采用了缓冲的思想,但是我觉得它缓冲的不够彻底,因为时不时总是要重新调整数组生成。

    在这里,我也实现了一个CharArrayBuffer的类,用来作为缓冲。

   

/**
 * Created by lsz on 2014/8/12.
 */
public class CharArrayBuffer {
    private static final int BUFSIZE = 1024*1024*2;//这里具体的大小看业务场景
    private char[] buf = new char[BUFSIZE];
    private int count = 0;
    public void append(char c){
         buf[count] = c;
         count++;
    }
    public String toString(){
        return new String(buf,0,count);
    }
    public void clean(){
        count = 0;
    }
}
    看到这个实现,这个类比StringBuffer少了一个要不断扩充的value数组的机制,但是更坑爹的两个问题,一个是BUFSIZE是固定的,如果越出怎么办,另外不停得new,并不是所有的buf都要那么大的,是不是很浪费。这里,我要解释下,其中BUFSIZE固定是因为上面说了,要根据业务内容来评估大小,比如保持一张网页的内容,肯定足够的。另外,空间浪费的问题,就是今天的重点,采用池化的思想来管理这些对象。

    池化是一个很经典的,用空间来换时间的思想(减少浪费和不停初始化的时间)。其中,连接池、对象池、缓冲池都是具体的表现。接下来我会实现一个简单的池,采用栈实现。

   

import sun.org.mozilla.javascript.internal.Synchronizer;

import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;

/**
 * Created by lsz on 2014/8/12.
 */
public class BufferPool {
    private static Long lock = 0l;
    private static BlockingDeque<CharArrayBuffer> bDeque = null;
    public  static CharArrayBuffer get(){
        if(bDeque == null) {
            synchronized(lock){
                if(bDeque == null){
                    bDeque = new LinkedBlockingDeque<CharArrayBuffer>(50);
                    for(int i = 0;i<50;i++){
                        try {
                            bDeque.putFirst(new CharArrayBuffer());
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        try {
            return bDeque.takeFirst();
        } catch (InterruptedException e) {
            e.printStackTrace();
            return null;
        }
    }
    public static void returnPool(CharArrayBuffer buf){
        try {
            buf.clean();
            bDeque.putFirst(buf);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

    简简单单写的,可能有什么遗漏。。。实现了最简单的“池”。通过get和returnPool就可以得到和返回池里面继续待用。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值