单例模式
就是始终是一个对象实例.它对外不提供构造函数,因此我们不能够同时产生多个对象.(常用语工具类,数据库连接类等等)
单例模式的调用:因为单例模式的构造方法是私有的,所以在其他类中我们是没有办法直接实例化它的.但是又因为她对外提供了一个获取类实例的方法,所以不论有多少类调用,他对外只可能产生一个类的实例
在People类中;创建静态私有对象p;创建getInstance()方法来返回对象p;其他类可以直接调用getInstance()方法获取对象p。
1.饿汉单例模式:即静态初始化的方式,它是类一加载就实例化对象,所以要提前占用系统资源,因此线程安全
public class People{ private static People p = new People(); private People(){ } public static People getInstance(){ return p; } }
2.懒汉单例模式 : 它使用了延迟加载来保证对象在没有使用之前,是不会进行初始化的。
缺点:线程不安全,当多个线程运行到getInstance()时,有可能会创建多个实例。
public class People{ private static People p; private People(){ } public static People getInstance(){ if(p == null){ p = new People(); } return p; } }
3.我们可以直接加上synchronized ,实现线程同步
class Singletion { private static Singletion singletion = null; private Singletion() { } public static synchronized Singletion getSingletion() { if (null == singletion) { singletion = new Singletion(); } return singletion; } }
实现同步会一定程度的使程序的并发度降低,我们可以在对此进行改进。
4.通过双重检查锁来保证程序的高并发和线程安全
1 class Singletion{ 2 private static Singletion singletion=null; 3 4 private Singletion() { 5 } 6 public static Singletion getSingletion(){ 7 if(null==singletion){ 8 synchronized (Singletion.class){ 9 if(null==singletion){ 10 singletion=new Singletion(); 11 } 12 } 13 } 14 return singletion; 15 } 16 }
这种写法使得只有在加载新的对象进行同步,在加载完了之后,其他线程在第7行就可以判断跳过锁的的代价直接到第14行代码了。做到很好的并发度。
5.利用枚举实现线程安全并且JVM安全的单例模式
// 线程安全,JVM安全的单例类 enum Singleton{ SINGLE } // 单例类的使用 class Test{ public static void main(String[] args) { Singleton s1 = Singleton.SINGLE; Singleton s2 = Singleton.SINGLE; Singleton s3 = Singleton.SINGLE; } }
6.用内部类实现线程安全的单例模式
class Singleton{ //02 定义一个静态内部类 private static class InnerClass{ static Singleton singleton=new Singleton(); } //03 public static Singleton getsingleton(){ return InnerClass.singleton; } //01 private Singleton(){ System.out.println("call Singleton()"); } }