享元模式在spring源码中的应用

回顾之前spring学习过程中学到的一些知识点,在连接池的运用中经常会运用到享元模式

我们看下源码,是怎么实现的?

先自定义一个redis连接池的工厂,叫做RedisDataSource


public class RedisDataSource {
    private static volatile JedisPool jedisPool;

    public static Jedis getJedis() {
        if (jedisPool == null) {
            synchronized (RedisDataSource.class) {
                if (jedisPool == null) {
                    JedisPoolConfig config = new JedisPoolConfig();
                    config.setMaxTotal(2);//最大连接数
//                    config.setMaxIdle(60);//最大空闲数
                    jedisPool =new JedisPool(config, "127.0.0.1", 6379);
                }
            }
        }

        return  jedisPool.getResource();
    }
    public static JedisPool getJedisPool(){
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(1000);//最大连接数
        config.setMaxIdle(60);//最大空闲数
        return new JedisPool(config, "127.0.0.1", 6379);
    }

}

RedisDataSource的静态getJedis()方法可以向外界公开一个获取Jedis连接对象的接口,但是创建Jedis'Pool的方式是采用的单例方式,也就是说JedisPool从始至终只有一份,但是Jedis连接可能有多个。

现在我们的连接池大小是2,连续打印3个从连接池获取到的Jedis对象,会发现进程卡住了,因为连接池最大只能装载2个链接,而我们现在要获取第三个链接,所以进程会卡住,不执行,但是如果我们主动关闭一个Jedis链接的话,第三个就可以使用了,而且复用了之前创建出来的Jedis对象。以下是打印出来的结果:

redis.clients.jedis.Jedis@58695725
redis.clients.jedis.Jedis@543588e6
redis.clients.jedis.Jedis@58695725

 所以首先有一个问题:

为什么在第三次获取Jedis对象的时候,会复用呢?这个被复用的Jedis对象是什么时候存到了jedispool中的呢?

//每次获取Jedis链接的时候,会去走这段代码:
p = (PooledObject)this.idleObjects.pollFirst();
//如果拿不到空闲的Jedis对象,那么创建一个新的
if (p == null) {
  p = this.create();

之后,当jedis对象调用了close()方法的时候,会去找到的他的datasource,也就是一开始创建它的Jedispool,然后执行下面的这个方法去释放资源,

public void close() {
        if (this.dataSource != null) {
            JedisPoolAbstract pool = this.dataSource;
            this.dataSource = null;
            if (this.client.isBroken()) {
                pool.returnBrokenResource(this);
            } else {
                pool.returnResource(this);
            }
        } else {
            super.close();
        }

    }

让这个Jedis对象添加到idleObjects中,变成一个空闲对象,

this.idleObjects.addFirst(p);

之后再从线程池获取jedis对象的时候,就是拿这个idleobject了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_34116044

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值