共享模式之享元模式

网友投稿 267 2022-09-19

共享模式之享元模式

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 是线程安全的,单个方法是原子的,线程安全的,但是并不能保证多个方法的组合是线程安全的。其他不可变类也一样。)

3. DIY,自定义连接池

例如:一个线上商城应用,QPS 达到数千,如果每次都重新创建和关闭数据库连接,性能会受到极大影响。 这时预先创建好一批连接,放入连接池。一次请求到达后,从连接池获取连接,使用完毕后再还回连接池,这样既节约了连接的创建和关闭时间,也实现了连接的重用,不至于让庞大的连接数压垮数据库。

关于synchronized

使用synchronized对连接池上锁,如果没有空闲连接,当前线程调用连接池对象的wait方法,让线程进入waitSet,进入等待状态。因为CAS不断循环的操作适合于短时间运行的代码片段。CAS利用CPU不停的尝试获取锁,由于线程获取连接池以后,需要进行的操作比较多,耗时较多,此时CAS使用的CPU还在不断的空转,浪费CPU资源。所以让其进入等待状态可以节省CPu资源。

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 {// 实现略}

以上实现没有考虑:         ● 连接的动态增长与收缩         ● 连接保活(可用性检测)         ● 等待超时处理         ● 分布式 hash 对于关系型数据库,有比较成熟的连接池实现,例如c3p0, druid等 对于更通用的对象池,可以考虑使用apache commons pool,例如redis连接池可以参考jedis中关于连接池的实现

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:151. 翻转字符串里的单词_Java实现_空间O(1)详解
下一篇:JDK1.8下ThreadPoolExecutor的官方实现
相关文章

 发表评论

暂时没有评论,来抢沙发吧~