单例模式

单例模式是最简单,很常见的设计模式。一般单例模式分为懒汉式和饿汉式。懒汉式涉及线程安全,而饿汉式在类加载时就已经生成实例,不涉及线程安全问题,但却不是懒加载。

除了懒汉式和饿汉式,还可以通过静态内部类和枚举创建单例模式。

单例模式用于只能有一个对象的场景。

/**
 *懒汉式,线程不安全。当有多个线程同时执行getInstance时,
 *很有可能出现多个实例。这种方式只适用于单线程的场景
 */
public class Singleton1 {
	//构造方法必须私有,对外屏蔽使用new关键字来创建对象
	private Singleton1(){}
	
	private static Singleton1 singleton1;
	
	public static Singleton1 getInstance() {
		if(singleton1==null){
			singleton1=new Singleton1();
		}
		return singleton1;
	}
}

/**
 *懒汉式,线程安全。和Singleton1相比,只在getInstance方法上使用synchronized关键字
 *进行了修饰。保证了getInstance()方法是同步执行的。但这种方式效率很低,当有多个线程需要获取实例时,
 *大多数线程只能等待操作getInstance()的线程释放锁。无论singleton2是否已经实例化,没有锁的线程
 *获取实例时都得等待(比如singleton2已经实例化了,应该直接就能获取到实例,但其他线程获取实例时还得先判断锁,
 *无锁才能获取,有锁还得等待。这样就造成了效率低下)
 */
class Singleton2{
	private Singleton2(){}
	
	private static Singleton2 singleton2;
	
	public static synchronized  Singleton2 getInstance() {
		if(singleton2==null){
			singleton2=new Singleton2();
		}
		return singleton2;
	}
}

/**
 *懒汉式,双重校验锁,在多线程的情况下可以保持高效。有效解决了Singleton2的低效率问题。
 *当多个线程执行getInstance()获取实例时,先判断singleton3是否已经实例化,一旦实例化
 *就直接获取实例,不用执行同步代码块来判断锁,也不会因为没有锁而进行等待,所以效率比Singleton2高。
 *在getInstance()中有两次判断singleton3是否为空。第一次判断很简单,如果不为空则线程直接获取,
 *为空则执行同步代码块创建实例。
 *第二次判断是在同步代码块中。因为可能多个线程第一次判断singleton3为null,都在等待执行同步代码块来创建新
 *实例。如果没有第二次判断,那么前面的线程执行完同步代码块,创建了新实例。后进入的线程再执行同步代码块,
 *又一次创建实例,这样就不能实现单实例了。
 */
class Singleton3{
	private Singleton3(){}
	
	 private volatile static Singleton3 singleton3; 
	 
	 public static Singleton3 getInstance(){
		 if(singleton3==null){
			 synchronized(Singleton3.class){
				 if(singleton3==null){
					 singleton3=new Singleton3();
				 }
			 }
		 }
		 
		 return singleton3;
	 }
}

/**
 *饿汉式,代码很简单,也最常用。这种方式在类加载时,直接就创建了对象。避免了多线程的同步问题,线程安全。
 *但这种没有采用懒加载(lazy loading),容易产生垃圾对象。
 *
 */
class Singleton4{
	private Singleton4(){}
	private static Singleton4 singleton4=new Singleton4();
	
	public static Singleton4 getInstance() {
		return singleton4;
	}
}


/**
 *采用静态内部类的方式实现单例模式。因为静态内部类只有在调用时才会被加载(不同于静态代码块在类加载时就执行),实现了懒加载,
 *达到双检锁一样的目的。但是又避免了使用同步代码块的繁琐。
 *这种方式,集成了饿汉式的简洁和双重检验懒汉式的线程安全。
 *优点:懒加载,多线程安全。
 */
class Singleton5{
	private Singleton5(){}
	
	//静态内部类只有在被调用时才会加载,是实现懒加载的充分条件。
	private static class SingletonHolder{
		static final Singleton5 SINGLETON5=new Singleton5();
	}
	
	public static Singleton5 getInstance(){
		return SingletonHolder.SINGLETON5;
	}
}


/**
 * 使用枚举类型创建单例模式,可以防止通过反射破坏单例(上面的几种方式,都可以通过反射机制破坏单例)
 * 这是实现单例模式的最佳方式。
 */
class Singleton6{
	private Singleton6(){
		System.out.println("正在创建Singleton6对象");
	}
	
	public static Singleton6 getInstance(){
		return MyEnum.INSTANCE.getInstance();
	}
	
	
	/**
	 *定义一个静态的内部枚举类型
	 */
	 static enum MyEnum{ 
     INSTANCE;
		 
	  private Singleton6 singleton6;
	  
	  //JVM会保证此方法绝对只调用一次,枚举的构造方法不能被反射
	  private MyEnum(){
		  singleton6=new Singleton6();
	  }
	  
	  public Singleton6 getInstance(){
		  return singleton6;
	  }
	  
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值