几种常见的单例模式

本文根据分布式系统基于redis获取的分布式锁的对象,简单对比几种单例模式。

需要引入依赖

       <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.36.Final</version>
        </dependency>

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>

        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.10.7</version>
        </dependency>

首先锁对象基于redis,创建该对象需要消耗一定的资源,而且一个系统中存在一个分布式锁对象即可,则可以创建单例对象

方式一:饿汉式,

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

/**
 *@description :  饿汉式
 *                      是否懒加载:否
 *                      是否多线程安全:是
 *                      实现难度:易
 *                      描述:比较常用,容易产生垃圾对象
 *                      优点:没有加锁,执行效率会提高
 *                      缺点:类加载就初始化,浪费内存
 *@data :2020-01-06 13:03
 *@version :1.0.0.1
 */
public class RedissionLock {
    //类加载就创建
    private static RedissonClient redissonClient = new RedissionLock().getRedissonClient();
    //初始化
    private RedissionLock(){
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword(null);
        redissonClient = Redisson.create(config);
    }
    //对外暴露对象
    public RedissonClient getRedissonClient(){
        return redissonClient;
    }
}

方式二:懒汉式

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

/**
 *@description :  懒汉式——已改进
 *                      是否懒加载:是
 *                      是否多线程安全:是
 *                      实现难度:易
 *                      描述:比较常用,改进后线程安全效率高
 *                      优点:懒加载,执行效率会提高
 *
 *@data :2020-01-06 13:03
 *@version :1.0.0.1
 */
public class RedissionLock1 {
    //类加载就创建
    private static RedissonClient redissonClient = null;
    //初始化
    private RedissionLock1(){
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword(null);
        redissonClient = Redisson.create(config);
    }
    //对外暴露对象
    public RedissonClient getRedissonClient(){
        /*双非空判断+synchronized锁,假如多个线程同时请求,首先判断redissonClient对象是否为空
         *如果为空,则在创建对象的代码块外加锁,因为只有调用一次创建方法才会实现单例。
         *拿到锁对象后再次判断redissonClient是否为空,(防止第二个线程在第一次判空时为true时获取锁后再次创建对象)
         *如果第一个线程释放锁后,此时对象一定是创建成功的,则第二个线程判断对象不为空,直接返回
         */
        if(redissonClient == null){
            synchronized (RedissionLock1.class){
                if(redissonClient == null){
                    new RedissionLock1();
                }
            }
        }
        return redissonClient;
    }
}

方式三:静态内部类之懒加载,也是我们项目中用的方式

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

/**
 *@description :  静态内部类
 *                      是否懒加载:是
 *                      是否多线程安全:是
 *                      实现难度:中等
 *                      描述:静态内部类创建单实例对象,静态对象一定是单例的
 *                      优点:懒加载,不用加锁,效率高
 *
 *@data :2020-01-06 13:03
 *@version :1.0.0.1
 */
public class RedissionLock2 {
    //类加载就创建
    private static RedissonClient redissonClient = null;
    //初始化
    private RedissionLock2(){
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword(null);
        redissonClient = Redisson.create(config);
    }

    private static class LazyHolder{
        private static final RedissionLock2 INSTANCE = new RedissionLock2();
    }

    //对外暴露对象
    public RedissonClient getRedissonClient(){
        return LazyHolder.INSTANCE.redissonClient;
    }
}

方式四:枚举方式,需要了解枚举机制

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

/**
 *@description :  枚举方式实现基于RedissionLock的获取分布式锁的单例对象
                  
                     枚举对象简单,安全,而且枚举类型是所用单例实现中
                  唯一一种不会被破坏的单例实现模式,最佳方式
 *@version :1.0.0.1
 */
public enum RedissionLockEnum {

    REDISSION_LOCK;
    //要创建的单例对象
    private RedissonClient redissonClient = null;

    //集群模式的配置信息
    //private String arrs = "redis://127.0.0.1:6379","redis://127.0.0.2:6379";
    //单机模式的配置信息
    private String arrs = "redis://127.0.0.1:6379";

    private  RedissionLockEnum(){
        Config config = new Config();
        if(arrs.contains(",")){
            config.useClusterServers().addNodeAddress(arrs).setPassword(null).setScanInterval(600000);
            System.out.println("调用私有的构造方法创建redis集群环境的单例对象");
        }else {
            config.useSingleServer().setAddress(arrs).setPassword(null);
            redissonClient = Redisson.create(config);
            System.out.println("调用私有的构造方法创建redis单机环境的单例对象");
        }
        redissonClient = Redisson.create(config);
    }

    public RedissonClient getRedissonClient(){
        return this.redissonClient;
    }


}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值