单例模式
模式意图:保证一个类只有一个实例,并提供几个全局访问点。
优点:节省内存,cpu资源
场景:
1.需要更严格的控制全局变量时,使用单例模式。
2.重量级的对象如线程池对象,数据库连接池对象/不需要多个实例的对象如工具类。
1.什么是单例模式?
java中单例模式是一种常见的设计模式,单例模式的写法有好几种,
常用的单例模式有懒汉式、饿汉式、双重效验锁、枚举、静态内部。
单例特点:
1.单例类只能有一个实例
2.单例类必须自己创建自己的唯一实例
3.单例类的构造器必须是私有的,不允许外界通过构造器创建对象
4.单例类是能通过放开静态方法向外界返回唯一的实例
2.为什么要使用单例模式呢?
1.为了保证一个类只能有一个单一的实例,也就是说你无法通过new来创建这个类的新实例
2.使用单例的好处:
1.当一个对象在程序内部只能有一个实例的时候,
它可以保证我们不会重复创建,而是始终指向同一个对象。
演变
类Singleton
1本类中添加公共的构造器 ,测试类中new 对象
把构造器改成私有的,测试类中则new 报错
2 new实例化 只能本类实例化
private 只能本类中用,所以在本类中创建一个成员变量=new Singleton() 。其他类中调用本类的成员变量,
加上static 关键字。 (jvm 加载顺序)
3 封装的思想,给成员变量私有化,给公共的set,get方法
难点
1>.构造器 private
为了不允许外界通过构造器创建对象
2>.static jvm加载顺序
jvm加载类时优先 加载静态的,其他的则是使用的时候才加载
封装的思想
锁synchronized
效率的问题
/**
* 饿汉式单例模式
*
* 不管是否使用,都会先初始化。
* 优点:保证只有一个实例
* 缺点:多线程县城不安全没有获取实例的时候,实例已经创建好了,
* 后续可能没有使用,浪费空间
* 解决:可以使用懒汉式单例模式
*/
class Singleton1{
//private 只能在本类下new 需要加static关键字 涉及到jvm运行机制
private static Singleton1 singleton1=new Singleton1();
//私有化构造器(禁止在类的外部直接new)
private Singleton1(){}
//公共的public 静态static的get方法
public static Singleton1 getInstance(){
return singleton1;
}
}
/**
* 懒汉式
* 在使用的时候才去初始化。
* 下面代码中将getInstance()变为synchronized方法,
* 保证了线程安全性;但是只有在第一次执行此方法时,
* 才真正需要同步,所以一旦初始化完毕后,就每次调用这个方法,
* 同步都是多余的。
*/
class Singleton2{
private static Singleton2 singleton2;
private Singleton2(){}
public static synchronized Singleton2 getInstance(){
if (null==singleton2) {
singleton2=new Singleton2();
}
return singleton2;
}
}
/**
* 双重判定锁
* 首先会检查实例是否创建,如果没有,才进行同步。
* 这样的方式是对懒汉模式的一次性能升级,
* 在getInstance()中减少使用同步,保证只有在第一次时会同步。
*/
class Singleton3{
/**必须使用volatile 修饰,保证多线程情况下Singleton3
*在多线程之间的可见性和禁止指令重排
*/
private volatile static Singleton3;
private Singleton3(){}
public static Singleton3 getInstance(){
if(null==singleton3){//避免每次加锁,只有第一次创建对象时才加锁
synchronized (Singleton3.class){//只允许一个线程进入
if(null==singleton3){//此处不多于,不需配合synchronized 一同使用
singleton3=new Singleton3();
}
}
}
return singleton3;
}
}
/**
*内部类实现单例模式
*/
class Singleton4{
//私有构造方法
private Singleton4(){
}
//静态内部类
private static class InnerClass{
//提供静态的成员变量,创建对象并赋值
static Singleton4 singleton4= new Singleton4();
}
//公共的静态get方法
public static Singleton4 getInstance(){
return InnerClass.singleton4;
}
}