package singleton; /* * 创建型|单例模式|饿汉式(静态常量) * 优缺点说明: * 1>优点:写法简单,类装载的时候完成实例化。避免了线程同步问题。 * 2>缺点:在类装载的时候就完成实例化,没有达到Lazy loading的效果。 * 如果从始至终没用过这个实例,则会造成内存浪费。 * 3>基于classloder机制避免了多线程的同步问题。不过instance在类 * 装载时就实例化,在单利模式中大多是都基于getinstance方法,但是导致 * 类装载的原因有很多种,因此不能确定有其它的方式(或者其它的静态方法) * 导致类装载,这时候初始化instance就没有达到lazy loading的效果。 * 4>结论:这种单例模式可用,可能造成内存浪费。 * */ public class HungryMS1 { public static void main(String[] args) { Singleton singleton1 = Singleton.getInstance(); Singleton singleton2 = Singleton.getInstance(); System.out.println(singleton1 == singleton2);// true System.out.println("singleton1 hashCode:" + singleton1.hashCode()); System.out.println("singleton2 hashCode:" + singleton2.hashCode()); } } class Singleton { //1 构造器私有化,外部能new private Singleton() { } //2 本类内部创建对象实例 private final static Singleton instance = new Singleton(); //3 对外提供一个共有静态方法,返回实例对象 public static Singleton getInstance() { return instance; } }
package singleton;
/*
* 创建型|单例模式|饿汉式(静态代码块)
* 优缺点说明:
* 1>优点:写法简单,类装载的时候完成实例化。避免了线程同步问题。
* 2>缺点:在类装载的时候就完成实例化,没有达到Lazy loading的效果。
* 如果从始至终没用过这个实例,则会造成内存浪费。
* 3>这种方式和静态变量的方式类似,只不过将类实例化的过程放在了静态代码块中,
* 也是在类装载的时候,就执行静态代码块中的代码,初始化类的实例。优缺点一致。
* 4>结论:这种单例模式可用,可能造成内存浪费。
* */
public class HungryMS2 {
public static void main(String[] args) {
Singleton2 singleton1 = Singleton2.getInstance();
Singleton2 singleton2 = Singleton2.getInstance();
System.out.println(singleton1 == singleton2);// true
System.out.println("singleton1 hashCode:" + singleton1.hashCode());
System.out.println("singleton2 hashCode:" + singleton2.hashCode());
}
}
class Singleton2 {
//1 构造器私有化,外部能new
private Singleton2() {
}
//2 本类内部创建对象实例
private static Singleton2 instance;
// 在静态代码块中,创建单利对象
static {
instance=new Singleton2();
}
//3 对外提供一个共有静态方法,返回实例对象
public static Singleton2 getInstance() {
return instance;
}
}
package singleton;
/*
* 创建型|单例模式|懒汉式(线程不安全)
* 优缺点说明:
* 1>优点:写起到了Lazy Loading的效果,但是只能在单线程下使用
* 2>缺点:如果在多线程下,一个线程进入if(singleton==null)判断语句块,还
* 未来得及往下执行,另一个线程也通过了这个判断语句,这时候就会产生多
* 个实例。所以在多线程环境下不可使用这种方式
* 3>结论:在实际开发中,不要使用这种方式
* */
public class SluggardS1 {
public static void main(String[] args) {
Singleton3 singleton1 = Singleton3.getInstance();
Singleton3 singleton2 = Singleton3.getInstance();
System.out.println(singleton1 == singleton2);// true
System.out.println("singleton1 hashCode:" + singleton1.hashCode());
System.out.println("singleton2 hashCode:" + singleton2.hashCode());
}
}
class Singleton3 {
private static Singleton3 instance;
private Singleton3() {
}
//提供一个静态的共有方法,当使用到该方法时,才会去创建instance
//懒汉式
public static Singleton3 getInstance() {
if(instance==null){
instance=new Singleton3();
}
return instance;
}
}
package singleton; /* * 创建型|单例模式|懒汉式(线程安全,同步方法) * 优缺点说明: * 1>优点:解决类线程不安全问题 * 2>缺点:效率太低,每个线程在执行getInstance()方法都要进行同步。方法进行同步效率低 * 3>结论:在实际开发中,不推荐使用这种方式 * */ public class SluggardS2 { public static void main(String[] args) { Singleton4 singleton1 = Singleton4.getInstance(); Singleton4 singleton2 = Singleton4.getInstance(); System.out.println(singleton1 == singleton2);// true System.out.println("singleton1 hashCode:" + singleton1.hashCode()); System.out.println("singleton2 hashCode:" + singleton2.hashCode()); } } class Singleton4 { private static Singleton4 instance; private Singleton4() { } //提供一个静态的共有方法,加入同步处理的代码,解决线程安全问题 //懒汉式 public static synchronized Singleton4 getInstance() { if(instance==null){ instance=new Singleton4(); } return instance; } }
package singleton; /* * 创建型|单例模式|懒汉式(线程安全,同步代码块) * 优缺点说明: * 1>本意是对同步方法进行改进,但是并不能起到线程同步的作用 * 3>结论:在实际开发中,不能使用这种方式 * */ public class SluggardS3 { public static void main(String[] args) { Singleton5 singleton1 = Singleton5.getInstance(); Singleton5 singleton2 = Singleton5.getInstance(); System.out.println(singleton1 == singleton2);// true System.out.println("singleton1 hashCode:" + singleton1.hashCode()); System.out.println("singleton2 hashCode:" + singleton2.hashCode()); } } class Singleton5 { private static Singleton5 instance; private Singleton5() { } //提供一个静态的共有方法,同步处理代码放入if下 //懒汉式 public static Singleton5 getInstance() { if(instance==null){ synchronized(Singleton5.class){ instance=new Singleton5(); } } return instance; } }
package singleton; /*创建型|单例模式|双重检查 * 1>双重检查概念是多线程开发中常使用到的,如代码中所示,进行了两次检查,可以保证线程安全 * 2>线程安全;延迟加载;效率较高(延时加载的实现) * 3>结论:在实际开发中,推荐使用这种单例设计模式 * */ public class DuplicationCheck { public static void main(String[] args) { DCSingleton singleton1 = DCSingleton.getInstance(); DCSingleton singleton2 = DCSingleton.getInstance(); System.out.println(singleton1 == singleton2);// true System.out.println("singleton1 hashCode:" + singleton1.hashCode()); System.out.println("singleton2 hashCode:" + singleton2.hashCode()); } } class DCSingleton { private static volatile DCSingleton instance; private DCSingleton() { } //提供一个静态的共有方法,加入双重检查代码,解决线程安全问题,同事解决懒加载问题 //同时保证了效率,推荐使用 public static DCSingleton getInstance() { if (instance == null) { synchronized (DCSingleton.class) { if (instance == null) { instance = new DCSingleton(); } } } return instance; } }
package singleton; /*创建型|单例模式|静态内部类 * 1>采用类装载机制保证初始化实例只有一个线程 * 2>静态内部类方式在单例类呗装载时不会立即实例化,而是在需要实例化时,调用 * getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化 * 3>类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程安全, * 在类进行初始化时,别的线程是无法进入的。 * 4>优点:避免了线程不安全,利用静态内部类特点实现延迟加载,效率高 * 5>结论:推荐使用 * */ public class StaticInner { public static void main(String[] args) { SISingleton singleton1 = SISingleton.getInstance(); SISingleton singleton2 = SISingleton.getInstance(); System.out.println(singleton1 == singleton2);// true System.out.println("singleton1 hashCode:" + singleton1.hashCode()); System.out.println("singleton2 hashCode:" + singleton2.hashCode()); } } class SISingleton { private static volatile SISingleton instance; private SISingleton() { } //写一个静态内部类,该类中有一个静态属性Singleton private static class SISingletonInstance { //JVM底层提供的类的装载机制保证线程安全 private static final SISingleton INSTANCE = new SISingleton(); } //提供一个静态的共有方法,直接返回SingletonInstance.INSTANCE public static synchronized SISingleton getInstance() { return SISingletonInstance.INSTANCE; } }
package singleton; /*创建型|单例模式|枚举 * 1>借助JDK1.5中添加的枚举来实现单例模式,不仅能变多线程同步问题,而且还能方式反序列化重新创建新的对象 * 2>这种方式是Effective Java作者Josh Bloch提倡的方式 * 3>结论:推荐使用 * */ public class EnumStyle { public static void main(String[] args) { ESingleton singleton1=ESingleton.INSTANCE; ESingleton singleton2=ESingleton.INSTANCE; System.out.println(singleton1 == singleton2);// true System.out.println("singleton1 hashCode:" + singleton1.hashCode()); System.out.println("singleton2 hashCode:" + singleton2.hashCode()); } } //使用枚举,可以实现单利 enum ESingleton{ INSTANCE; public void method(){ System.out.println("ok~"); } }
原文:https://www.cnblogs.com/Arrogance/p/14615451.html