天天看點

共享模式之享元模式

共享模式之享元模式
public static Long valueOf(long l) {
        final int offset = 128;
        if (l >= -128 && l <= 127) { // will cache
            return LongCache.cache[(int)l + offset];
        }
        return new Long(l);
}      

注意:

Byte, Short, Long 緩存的範圍都是 -128~127

Character 緩存的範圍是 0~127

Integer的預設範圍是 -128~127

        最小值不能變

        但最大值可以通過調整虛拟機參數 `

        -Djava.lang.Integer.IntegerCache.high` 來改變

Boolean 緩存了 TRUE 和 FALS

2.2 String 串池

        享元模式、不可變類。(詳情見jvm第一天,記憶體結構文章對串池的記錄)

2.3 BigDecimal BigInteger

        享元模式、不可變類。(用AtomicReference<BigDecimal> ,保護BigDecimal ,是因為雖然BigDecimal 是線程安全的,單個方法是原子的,線程安全的,但是并不能保證多個方法的組合是線程安全的。其他不可變類也一樣。)

3. DIY,自定義連接配接池

        例如:一個線上商城應用,QPS 達到數千,如果每次都重新建立和關閉資料庫連接配接,性能會受到極大影響。 這時預先建立好一批連接配接,放入連接配接池。一次請求到達後,從連接配接池擷取連接配接,使用完畢後再還回連接配接池,這樣既節約了連接配接的建立和關閉時間,也實作了連接配接的重用,不至于讓龐大的連接配接數壓垮資料庫。
class Pool {
    // 1. 連接配接池大小
    private final int poolSize;
    // 2. 連接配接對象數組
    private Connection[] connections;
    // 3. 連接配接狀态數組 0 表示空閑, 1 表示繁忙
    private AtomicIntegerArray states;
    // 4. 構造方法初始化
    public Pool(int poolSize) {
        this.poolSize = poolSize;
        this.connections = new Connection[poolSize];
        this.states = new AtomicIntegerArray(new int[poolSize]);
        for (int i = 0; i < poolSize; i++) {
            connections[i] = new MockConnection("連接配接" + (i+1));
        }
    }
    // 5. 借連接配接
    public Connection borrow() {
        while(true) {
            for (int i = 0; i < poolSize; i++) {
// 擷取空閑連接配接
                if(states.get(i) == 0) {
                    if (states.compareAndSet(i, 0, 1)) {
                        log.debug("borrow {}", connections[i]);
                        return connections[i];
                    }
                }
            }
            // 如果沒有空閑連接配接,目前線程進入等待
            synchronized (this) {
                try {
                    log.debug("wait...");
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    // 6. 歸還連接配接
    public void free(Connection conn) {
        for (int i = 0; i < poolSize; i++) {
            if (connections[i] == conn) {
                states.set(i, 0);
                synchronized (this) {
                    log.debug("free {}", conn);
                    this.notifyAll();
                }
                break;
            }
        }
    }
}

class MockConnection implements Connection {
// 實作略
}