地址:https://github.com/zhang-xiaoxiang/patter23
或者https://github.com/zhang-xiaoxiang/DesignPatterns23
一般三步走,1初始化2构造器私有3提供获取实例的方法
1 单例模式---饿汉式
package com.demo.singleton;
/**
* SingletonDemo1:单例模式---饿汉式
*
* 优点:线程安全
* 缺点:没有延迟加载的优势(即容易造成不分青红皂白new了个可能暂时无用的单例对象从而造成资源浪费)
*
* @author zhangxiaoxiang
* @date 2019/8/9
*/
public class SingletonDemo1 {
/**
* 1 类初始化(既然是饿汉那么上来就new了再说呗)
* 这里说明一下为什么声明成static,1是语法要求Non-static field 'instance' cannot be referenced from a static context,
* 为了给外部提供一个不是new出实例的方法,采用的是提供一个静态方法getInstance(),静态方法调动的必须是静态的变量;2是让外部不能以任何方式引用this 或super
* 总之就是被迫的使用static,记住就行了哈
*/
private static SingletonDemo1 instance = new SingletonDemo1();
/**
* 2 私有构造器
* 这里说明一下private(在本类的如果要继续new对象可以,private,public修饰构造器没有区别,类的内部操作属性和方法统统具有可见性,
* 但是外部调用该类,必须使用private修饰以防止外部new出新对象,所以这里必须是private修饰构造器,后面设计到的单例模式的其他方式都是这个操作,不在后文叙述)
*/
private SingletonDemo1() {
}
/**
* 3:提供获取单实例方法,方法没有同步(加锁),调用效率高!
* 说明一下,既然不让外部new对象,但是至少得给个方式让外部产生一个单实例吧,那么这里"被迫"使用静态方法,而且这也是最科学的
*/
public static SingletonDemo1 getInstance() {
return instance;
}
//强烈提示:不要在本类使用main方法测试,因为本类private是控制不了为私有,所以在其他类测试哈
}
/**
* test01:测试类,为了方便观察测试,直接写在这里测试(也可以单独在外部写个测试类)
* @author zhangxiaoxiang
* @date 2019/8/9
*/
class Test01 {
public static void main(String[] args) {
SingletonDemo1 instance = SingletonDemo1.getInstance();
SingletonDemo1 instance2 = SingletonDemo1.getInstance();
System.out.println(instance);
System.out.println(instance2);
//true
System.out.println(instance == instance2);
}
}
2 单例模式---懒汉式 不推荐
package com.demo.singleton;
/**
* SingletonDemo2:单例模式---懒汉式
* 优点:延迟加载(资源利用合理,用的时候才new)
* 缺点:synchronized加了线程安全效率低,不加线程不安全效率高
*
* @author zhangxiaoxiang
* @date 2019/8/9
*/
public class SingletonDemo2 {
/**
* 1:类初始化(既然是懒汉式,那就懒得不急着new对象)
*/
private static SingletonDemo2 instance;
/**
* 2:私有化构造器
*/
private SingletonDemo2() {
}
/**
* 3:提供获取单实例方法(静态工厂方法)
* 这里加synchronized和不加是对线程安全的考虑,不加线程不安全,调用效率高一些,反之线程安全效率低
* 这个地方可以优化,可以产生衍生版本,这个是屌丝版本哈
*/
public static synchronized SingletonDemo2 getInstance() {
//如果方法不加锁,多个线程(并发环境下)同时访问到这段代码的时候会出现"判断失误",所以这里加了锁保证线程安全
if (instance == null) {
instance = new SingletonDemo2();
}
return instance;
}
}
/**
* Test02:单例模式---懒汉式
*
* @author zhangxiaoxiang
* @date 2019/8/9
*/
class Test02 {
public static void main(String[] args) {
SingletonDemo2 instance = SingletonDemo2.getInstance();
SingletonDemo2 instance2 = SingletonDemo2.getInstance();
System.out.println(instance);
System.out.println(instance2);
//true
System.out.println(instance == instance2);
}
}
3单例模式---双重同步锁(懒汉模式衍生版本)
package com.demo.singleton;
/**
* SingletonDemo3:单例模式---双重同步锁(懒汉模式衍生版本)
*
* 优点:线程安全(因为加了volatile)
*
* volatile作用:解决并发问题,以下会涉及到Java内存模型的知识
* 主要应用1:修饰线程的标志,2:就是单例模式的双重检测机制
*
* @author zhangxiaoxiang
* @date 2019/8/9
*/
public class SingletonDemo3 {
/**
* 1:初始化对象 使用volatile解决并发问题 单例对象 volatile + 双重检测机制 -> 禁止指令重排
*/
private volatile static SingletonDemo3 instance = null;
/**
* 2:构造器私有化
*/
private SingletonDemo3() {
}
/**
* 3:提供获取单实例方法(就是个静态工厂方法哈)
*
* @return
*/
public static SingletonDemo3 getInstance() {
//这里前面如果不加volatile,那么后面的双重判断将会出现"误判",导致线程不安全,所以加了保证安全
//第一重检查锁定
if (instance == null) {
synchronized (SingletonDemo3.class) {
//第二重检查锁定
if (instance == null) {
synchronized (SingletonDemo3.class) {
//注意:非原子操作
instance = new SingletonDemo3();
}
}
}
}
return instance;
}
}
/**
* Test03:双重检查锁测试
*
* @author zhangxiaoxiang
* @date 2019/8/9
*/
class Test03 {
public static void main(String[] args) {
SingletonDemo3 instance = SingletonDemo3.getInstance();
SingletonDemo3 instance2 = SingletonDemo3.getInstance();
System.out.println(instance);
System.out.println(instance2);
//true
System.out.println(instance == instance2);
}
}
4单例模式---静态内部类(饿汉模式衍生版本)推荐使用
package com.demo.singleton;
/**
* SingletonDemo4:单例模式---静态内部类(饿汉模式衍生版本)
*
* (推荐使用)
* 优点:线程安全,并且实现了延时加载(调用效率高)!
*
* @author zhangxiaoxiang
* @date 2019/8/9
*/
public class SingletonDemo4 {
/**
* 1:初始化对象(使用的静态内部类方式)
*/
private static class SingletonClassInstance {
private static final SingletonDemo4 INSTANCE = new SingletonDemo4();
}
/**
* 2:构造器私有化
*/
private SingletonDemo4(){
}
/**
* 3提供获取实例的方法,该方法没有同步,调用效率高!
* @return
*/
public static SingletonDemo4 getInstance(){
return SingletonClassInstance.INSTANCE;
}
}
/**
* Test04:静态内部类实现单例模式测试
*
* @author zhangxiaoxiang
* @date 2019/8/9
*/
class Test04 {
public static void main(String[] args) {
SingletonDemo4 instance = SingletonDemo4.getInstance();
SingletonDemo4 instance2 = SingletonDemo4.getInstance();
System.out.println(instance);
System.out.println(instance2);
//true
System.out.println(instance == instance2);
}
}
5单例模式---枚举实现
package com.demo.singleton;
/**
* SingletonDemo5:单例模式---枚举实现
*
* 优点:这个是线程最安全,抗并发能力最强的
* 缺点:没有延时加载
* @author zhangxiaoxiang
* @date 2019/8/9
*/
public enum SingletonDemo5 {
/**
* 这个枚举元素,本身就是单例对象!天然单例
*/
INSTANCE;
/**
* 添加自己需要的操作!
*/
public void singletonOperation(){
System.out.println("枚举是天生的单例!");
}
}
/**
* Test05:枚举式实现单例模式测试
*
* @author zhangxiaoxiang
* @date 2019/8/9
*/
class Test05 {
public static void main(String[] args) {
SingletonDemo5 instance=SingletonDemo5.INSTANCE;
SingletonDemo5 instance2=SingletonDemo5.INSTANCE;
System.out.println(instance);
System.out.println(instance2);
//true
System.out.println(instance==instance2);
}
}
6单例模式---枚举模式2 推荐使用
package com.demo.singleton;
/**
* SingletonDemo6:单例模式---枚举模式2
*
* 推荐使用
* 优点:线程最安全
*
* @author zhangxiaoxiang
* @date 2019/8/12
*/
public class SingletonDemo6 {
/**
* 1:初始化
*/
private enum Singleton {
/**
* 枚举实例
*/
INSTANCE;
private SingletonDemo6 singleton;
/**
* JVM保证这个方法绝对只调用一次
*/
Singleton() {
singleton = new SingletonDemo6();
}
public SingletonDemo6 getInstance() {
return singleton;
}
}
/**
* 2:私有构造函数
*/
private SingletonDemo6() {
}
/**
* 3:提供一个获取单实例的方法
*
* @return
*/
public static SingletonDemo6 getInstance() {
return Singleton.INSTANCE.getInstance();
}
}
/**
* Test06:枚举单例测试2
*
* @author zhangxiaoxiang
* @date 2019/8/12
*/
class Test06 {
public static void main(String[] args) {
SingletonDemo6 instance = SingletonDemo6.getInstance();
SingletonDemo6 instance2 = SingletonDemo6.getInstance();
System.out.println(instance);
System.out.println(instance2);
//true
System.out.println(instance == instance2);
}
}
7单例模式---防止反射和反序列化漏(懒汉式衍生版本2)
package com.demo.singleton;
import java.io.ObjectStreamException;
import java.io.Serializable;
/**
* SingletonDemo7:单例模式---防止反射和反序列化漏(懒汉式衍生版本2)
*
* 优点:线程安全且带有延迟
* 缺点:调用效率低
*
* @author zhangxiaoxiang
* @date 2019/8/9
*/
public class SingletonDemo7 implements Serializable {
/**
* 1:类初始化时,不初始化这个对象(延时加载,真正用的时候再创建)。
*/
private static SingletonDemo7 instance;
/**
* 2:私有化构造器
*/
private SingletonDemo7(){
if(instance!=null){
throw new RuntimeException();
}
}
/**
* 3:提供一个单实例方法,方法同步,调用效率低!
* @return
*/
public static synchronized SingletonDemo7 getInstance(){
if(instance==null){
instance = new SingletonDemo7();
}
return instance;
}
/**
* 反序列化时,如果定义了readResolve()则直接返回此方法指定的对象。而不需要单独再创建新对象!
* @return
* @throws ObjectStreamException
*/
private Object readResolve() throws ObjectStreamException {
return instance;
}
}
/**
* Test06:防止反射和反序列化漏测试
*
* @author zhangxiaoxiang
* @date 2019/8/12
*/
class Test07{
public static void main(String[] args) {
SingletonDemo7 instance = SingletonDemo7.getInstance();
SingletonDemo7 instance2 = SingletonDemo7.getInstance();
System.out.println(instance);
System.out.println(instance2);
//true
System.out.println(instance==instance2);
}
}