java设计模式
单例设计模式
本章主要讲解单例设计模式有几种,并由代码引入,以及涉及的相关问题都会展示,欢迎各位看客点评,如有错误请指出~
第一种:饿汉式(静态变量)
class Singleton {
//1. 构造器私有化, 外部能new
private Singleton() {
}
//2.本类内部创建对象实例
private final static Singleton instance = new Singleton();
//3. 提供一个公有的静态方法,返回实例对象
public static Singleton getInstance() {
return instance;
}
}
分析:
第一步首先就是私有化私有方法,然后创建一个自己的静态变量,并提供一个get取值的方法,返回这个静态变量,很简单就完成了,代码如上。(jdk中Runtime就用的这个)
问题:
直接使用静态实例化后,无线程安全问题,但是每次你的服务启动了,对象实例化了,然后你在整个工程中加入都没用过这个对象,但是他始终存在内存中,所以浪费内存。不建议使用,除非你知道一定会用到这个对象。
第二种:饿汉式(静态变量,跟一类似)
class Singleton {
//1. 构造器私有化, 外部能new
private Singleton() {
}
//2.本类内部创建对象实例
private static Singleton instance;
static { // 在静态代码块中,创建单例对象
instance = new Singleton();
}
//3. 提供一个公有的静态方法,返回实例对象
public static Singleton getInstance() {
return instance;
}
}
分析:
把第一种改造下,把实例化放在静态代码块中,当类装载的时候实例化
问题:优缺点跟第一种一样。
第三种:懒汉式(1)
class Singleton {
private static Singleton instance;
private Singleton() {}
//提供一个静态的公有方法,当使用到该方法时,才去创建 instance
//即懒汉式
public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
分析:
私有化构造,然后将实例化放在取值的方法里,并判断当为空的时候在创建,第一次创建过后,因为是静态的,所以再走这个方法时,发现已经实例化了,就会直接返回,这样避免了内存浪费。
问题:
多线程时,会有问题,也就线程不安全,当第一条线程走到 if 时,然后判断为空,进去了,然后此时,cpu调度了第二条线程,第二条也走到 if 时,然后判断为空,进去了,此时执行了两次new!!问题就出现了(不推荐)
第四种:懒汉式(2)
// 懒汉式(线程安全,同步方法)
class Singleton {
private static Singleton instance;
private Singleton() {}
//提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题
//即懒汉式
public static synchronized Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
分析:
将取值方式添加synchronized ,直接同步,避免线程不安全
问题:
并发时效率非常低
第五种:懒汉式(3)
// 懒汉式
class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if(instance == null) {
synchronized (Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
分析:
这个就不解释了,毫无用处,忽略吧,为什么列出来?因为真有人这么玩。。。
第六种:懒汉式(3)
// 懒汉式(线程安全,同步方法)
class Singleton {
private static volatile Singleton instance;
private Singleton() {}
//提供一个静态的公有方法,加入双重检查代码,解决线程安全问题, 同时解决懒加载问题
//同时保证了效率, 推荐使用
public static Singleton getInstance() {
if(instance == null) {
synchronized (Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
分析:
当为空时,同步代码块创建,否则直接返回
问题:
双重检查代码,解决线程安全问题, 同时解决懒加载问题,同时保证了效率, 推荐使用,问题就是没问题!!!哈哈哈
第七种:懒汉式(4)
// 静态内部类完成, 推荐使用
class Singleton {
private static volatile Singleton instance;
//构造器私有化
private Singleton() {}
//写一个静态内部类,该类中有一个静态属性 Singleton
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
//提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE
public static synchronized Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
分析:
放在静态的内部类中,因为Singleton 类加载的时候 不会加载静态内部类,所以,也是懒加载,推荐使用
volatile 自己百度吧,很简单
问题:
没问题
第八种:枚举式
//使用枚举,可以实现单例, 推荐
enum Singleton {
INSTANCE; //属性
public void sayOK() {
System.out.println("ok~");
}
}
分析:
直接用1.5加的枚举,方便简洁
问题:
解决序列化问题等,推荐使用(这个多简洁,手动滑稽)