java 单例模式

一:单例模式的概述

单例模式是在 java中一种常见的设计模式,这种类型的设计模式属于一种创建型模式,这种模式提供了一个创建对象的最佳模式,在模式中一个类只能创建一个对象,该类负责创建自己的对象,并且只有一个实例,私有构造方法,即表示不能再类的外部实例化该类的对象,只能通过该类提供的公有方法来返回该类的一个实例对象。

二:单例类的基础

单例模式的基础:一个 类只有一实例,并为整个系统提供一个全局访问点,

结构:

                                     

类图分为三部分:

类名,属性,方法,

《》表示注释信息,+ 代表public,-代表private,#代表 protected,

下划线代表 属相或方法为 静态,

单例模式三要素:

私有的构造方法,

指向自己实例的私有静态引用,

以自己实例为返回类型的公有静态方法,

 

三:单例类的实现

1:两种实现方式

我们根据对单例类对象的两种加载方式 ,分为立即加载,和延迟加载,对应两种模式;为饿汉模式和懒汉模式,

2:饿汉模式的实现

根据定义:饿汉模式即为在类创建的时候,就已经将类的实例对象创建好了,饿汉模式在多线程的模式下为安全模式,在多线程的情况下 也保证只有一个实例对象。

public class SingletonDemo1 {
//指向自己实例的私有静态 引用
	private static SingletonDemo1 sing=new SingletonDemo1();
// 私有的构造方法
	private SingletonDemo1(){}
//以自己实例为返回值的静态 公有方法
	public static SingletonDemo1 getInstance(){
		return sing;
	}
	
}

3:懒汉模式(线程不安全的实现)

懒汉模式即为只有在我们需要的时候才会创建实例对象,延迟加载

public class SingletonDemo2 {
// 指向自己实例的私有静态引用
	private static SingletonDemo2 sing;
// 私有的构造方法
	private SingletonDemo2(){}
// 以自己实例为返回值的静态公有方法
	public static SingletonDemo2 getInstance(){
		if (sing==null){
			sing= new SingletonDemo2();
		}
		return sing;
		}
}

3:在多线程环境下的测试

public class Test {
	public static void main(String[] args) {
		
		// 开启 10 个 线程
		Thread [] threads= new Thread[10];
		
		for(int i=0;i<threads.length;i++){
			threads[i]=new TestThread();
		}
		for(int i=0;i<threads.length;i++){
			threads[i].start();
		}
		
	}

}


class TestThread extends Thread{
	public void run(){
		int hash =SingletonDemo1.getInstance().hashCode();
	    System.out.println(hash);
	}
}

 

在多线程的环境下,我们可以看到,饿汉模式只返回了同一个对象,

 

懒汉模式可能会返回多个实例,即线程不安全。

三:懒汉模式多线程下安全的实现

1:使用synchronized 方法

public class SingletonDemo3 {
	//指向 自己实例的私有静态 引用
	private static SingletonDemo3 sing;
	// 私有构造方法
	private SingletonDemo3(){
		
	}
	// 以自己实例 为 返回值的静态 公有方法 临界 对临界资源加锁
	public  static synchronized SingletonDemo3 getInstance(){
		if(sing == null){
			sing =new SingletonDemo3();
		}
		return sing;
	}

}

二:使用同步代码块

public class SingletonDemo4 {
	 // 指向自己实例的私有静态引用
	private static SingletonDemo4 sing;
	// 私有构造方法
	private SingletonDemo4 (){}
	
	// 以自己实例为 返回值 的静态 公有方法 临界资源加锁 同步 代码块
	public static  SingletonDemo4 getInatance(){
		 synchronized(SingletonDemo4.class){
			 if(sing == null){
				 sing =new SingletonDemo4();
			 }
			 return sing;
		 }
	}
}

3:使用私有静态内部类来实现延迟加载

public class SingletonDemo5 {
	// 私有 静态 内部类 实现 延迟 加载 即 需要 时 加载
        private static class Handle{
        	private static SingletonDemo5 sing=new SingletonDemo5();
        }
	// 私有构造方法
        private SingletonDemo5(){}
        
    // 返回 实例 对象的方法
        public static SingletonDemo5 getInstance(){
        	return Handle.sing;
        }
}

4:使用双重检查机制

public class SingletonDemo6 {
	// 被 volatile 关键字修饰的 对象实例
	private static volatile SingletonDemo6 sing;
	
	// 私有的构造 方法
	private SingletonDemo6(){}
	//  返回 对象 实例 ,双重检查 机制
	
	
	public  static SingletonDemo6 getInstance(){
		if(sing ==null){
			synchronized(SingletonDemo6.class){
				// 只有在 第一次 创建 时 才 会执行
				if(sing ==null){
					sing= new SingletonDemo6();
				}
			}
			
		}
		
		return sing;
	}
}

5:使用ThreadLocal 实现懒汉式单例

public class SingletonDemo7 {
    // ThreadLocal 线程局部变量
    private static ThreadLocal<SingletonDemo7> threadLocal = new ThreadLocal<SingletonDemo7>();
    private static SingletonDemo7 sing = null;    // 
 
    private SingletonDemo7(){}
 
    public static SingletonDemo7 getSingleton4(){
        if (threadLocal.get() == null) {        // 第一次检查:该线程是否第一次访问
            createSingleton4();
        }
        return sing;
    }
 
    public static void createSingleton4(){
        synchronized (SingletonDemo7.class) {
            if (sing== null) {          // 第二次检查:该单例是否被创建
                sing = new SingletonDemo7();   // 只执行一次
            }
        }
        threadLocal.set(sing);      // 将单例放入当前线程的局部变量中 
    }
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值