java基础之单例模式
来源:互联网 发布:新材料在线软件 编辑:程序博客网 时间:2024/06/06 12:22
首先单例模式就是说一个类的对象从始至终只有一个,即使再去申请该类的时候,也还是会返回给程序上次已经返回的对象。
单例模式的时候需要注意有两种方法,懒汉式(真正使用的时候才会初始化该对象)和饿汉式(类在加载的时候就会初始化该对象),但是在使用懒汉式的时候就需要注意线同步的问题。
1.懒汉式
普通懒汉式
public Class Singleton { private static Singleton single = null; private Singleton(); // 构造方法为私有化,禁止其他类初始化 public static Singleton getInstance() { if(single == null) { single = new Singleton(); } return single; }}
这样我们在需要使用该类的对象的时候就直接调用getInstance方法就可以获取到了。
但是有个问题,懒汉式在多线程情况下回出现两个线程先后进入,然后造成对象多次分配的情况。
举个例子,线程一先判断,由于single对象为空,因此开始初始化,但是还没有初始化的时候,线程二又进来判断,这样两个都是判断的为null,结果两个都进行了new,产生了两个对象。
这样就引入了一个新的,带锁的单例模式
加同步的懒汉模式
为了在多线程的情况下能正常工作,对于getInstance方法加上同步
public Class Singleton { private static Singleton single = null; private Singleton(); // 构造方法为私有化,禁止其他类初始化 public static synchronized Singleton getInstance() { if(single == null) { single = new Singleton(); } return single; }}
这样在线程1进入getInstance方法的时候其他线程就不会进入该方法去进行判断对象是否为空,不会出现多线程的时候不同步的情况。
但同步的懒汉模式有一个性能问题,这样会导致每次进入getInstance都会同步。
双重锁检查
private volatile static Singleton single;public static Singleton getInstance() { if(single == null) { synchronized(Singleton.class) { if(single == null) { single = new Singletoon(); } } } return single;}
只有在single没有被初始化的时候,才会进行同步初始化single对象。
注意这里对于single添加了修饰符volatile,这是为了防止在多线程的情况下出现问题。
2.饿汉模式
饿汉模式就是类在加载的时候就对single进行初始化了。
public class Singleton { private Singleton single = new Singleton(); private Singleton(); public Singleton getInstance() { return single; }}
对于饿汉式的单例模式而言,天生就是线程安全的,但是在JVM加载类的时候就对单例类的对象进行了初始化,因此如果该对象只用一两次,并且使用时机比较靠后的话,饿汉式单例模式就会影响系统性能
但是懒汉式单例模式,只有在程序中需要使用该对象的时候才会进行初始化,这样就会节省系统资源。
3.实际项目中的一些技巧
前一段时间在项目中碰见了使用jedisPoold的场景,但是在使用JedisPool的时候可以获取到JedisPool的对象,但是在获取Jedis对象的时候就会报不能获取资源的异常。当时自己的代码是这样写的。
public class JedisUtil { private static JedisPool jedisPool = null; private static final JedisUtil util = new JedisUtil(); private JedisUtil() { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(-1); config.setMaxIdle(1000); try { String redisAddress = 获取redis地址 jedisPool = new JedisPool(config, redisAddress, 6379); } catch (Exception e) { e.printStackTrace(); } } public static JedisUtil getInstance() { return util; } public static void set(String key, String value) { Jedis jedis = null; try { jedis = getConnect(); jedis.set(key, value); } catch(JedisConnectionException e) { e.printStackTrace(); } catch(Exception e) { e.printStackTrace(); } finally { if(jedis != null) { jedis.close(); } } } private static Jedis getConnect() { return jedisPool.getResource(); }}
但是由于redisAddress在传过来的时候可能每次不太一样,因此这样写的时候就不是一个单例模式了。
归根到底还是自己对于单例的理解不够,单例说的是一个资源在系统运行过程中只会有一个实例,在这个例子中的资源指的是jedisPool,而不是util,而util在实际使用过程中他可以理解为一个媒介,通过它去使用资源。
最后经过修改,这个工具类可以写为下面的样子
public class JedisUtils { private static final JedisUtils util = new JedisUtils(); private static Map<String, JedisPool> jedisPools = new ConcurrentHashMap<>(); private JedisUtils() { } public static JedisUtils getInstance() { return util; } public static void set(String key, String value, String redisAddress) { // 真正使用jedispool的时候再从里面获取 // 没有的话先创建jedisPool if(!jedisPools.containsKey(redisAddress)) { generateJedisPool(redisAddress); } Jedis jedis = null; try { jedis = getConnect(redisAddress); jedis.set(key, value); } catch(JedisConnectionException e) { e.printStackTrace(); } catch(Exception e) { e.printStackTrace(); } finally { if(jedis != null) { jedis.close(); } } } private static void generateJedisPool(String redisAddress) { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(-1); config.setMaxIdle(1000); try { JedisPool jedisPool = new JedisPool(config, redisAddress, 6379); jedisPools.put(redisAddress, jedisPool); } catch (Exception e) { e.printStackTrace(); } } private static Jedis getConnect(String redisAddress) { JedisPool jedisPool = jedisPools.get(redisAddress); return jedisPool.getResource(); }}
- Java基础之单例模式
- java基础之单例模式
- java基础之单例模式
- java基础之单例模式
- java基础之设计模式之单例模式
- java基础之----设计模式单例设计模式
- java基础之设计模式(1)--单例模式
- JAVA中的基础---设计模式之单例模式
- Java基础----单例模式
- java基础---单例模式
- 黑马程序员-Java基础-多线程之单例模式总结
- Java基础菜鸟之单例设计模式
- 黑马程序员-------Java基础之单例设计模式
- Java基础复习之三:单例模式
- 黑马程序员-JAVA基础之单例设计模式
- 黑马程序员----java基础之单例设计模式
- Java基础学习记录之单例模式(singleton)
- Java基础-设计模式-单例模式
- zabbix 安装
- 经典算法之暴力匹配算法(字符串)
- leetcode 535. Encode and Decode TinyURL 编码和解码精简URL地址
- JNI基础知识
- shiro权限定义的三种方法
- java基础之单例模式
- 45-Jump Game II
- 【1701H1】【穆晨】【171217】连续第六十八天总结
- 洛谷P2023 && bzoj1798 [AHOI2009]维护序列
- c++课设学生成绩与学籍管理系统
- 171217-进制转换【连续第五十三天】
- 牛客算法--第六章
- 如何在Apache官网下载Tomcat
- 【python】*与** 参数问题