五种单例模式

今天算是完完整整把老高的单例模式看了,差不多也懂了,个别不懂的再补吧,下面介绍一下5种单例模式:

  饿汉式实现:线程安全,调用效率高。但是,不能延时加载。

  懒汉式实现:线程安全,调用效率不高。但是,可以延时加载。

  双重检测锁式:由于JVM底层内部模型原因,偶尔会出现问题,不建议使用。

  静态内部类式:线程安全,调用效率高,可以延时加载。

  枚举式:线程安全,调用效率高。但是,不能延时加载(避免反射和反序列化的漏洞)。

以下先介绍一下5种单例模式:

  饿汉式实现:

/**
 *单例模式:饿汉模式
 *线程安全,调用效率高。但是,不能延时加载
 * 
 * @author cookie
 *
 */
public class SingletonDemo01 {
	//类初始化时,立刻加载这个对象(没有延时加载的优势)。线程是天然安全
	private static SingletonDemo01 instance = new SingletonDemo01();
	private SingletonDemo01(){}
	//方法没有同步,线程安全,调用效率高。但是,不能延时加载
	public static SingletonDemo01 getInstance(){
		return instance;
	}
}

  懒汉式实现:

/**
 * 单例模式:懒汉模式
 * 线程安全,调用效率不高。但是,可以延时加载
 * 真正用的时候才加载,资源利用率高了。
 * @author cookie
 *
 */
public class SingletonDemo02 {
	//类加载时,不初始化对象(延时加载:资源利用率高)
	private static SingletonDemo02 instance;
	private SingletonDemo02(){}
	
	//synchronized 防止并发量高的时候,出现多个对象
	//方法同步,调用效率低,
	public static synchronized SingletonDemo02 getInstance(){
		if(instance==null){//真正用的时候才加载
			instance = new SingletonDemo02();
		}
		return instance;
	}
}

  双重检测锁式

/**
 * 单例模式:双重检验锁式 结合懒汉式和饿汉式的优点,但由于JVM底层内部模型原因,偶尔会出现问题,不建议使用
 * 
 * @author cookie
 * 
 */
public class SingletonDemo03 {
	private volatile static SingletonDemo03 instance = null;

	private SingletonDemo03() {
	}

	public static SingletonDemo03 getInstance() {
		if (instance == null) {
			synchronized (SingletonDemo03.class) {// 1
				if (instance == null) {// 2
					instance = new SingletonDemo03();// 3
				}
			}
		}
		return instance;
	}
}

  静态内部类式

/**
 * 单例模式:静态内部类实现单例模式。 优点:线程安全,调用效率高,实现延时加载。
 * 
 * @author cookie
 * 
 */
public class SingletonDemo04 {
	// 类加载时静态内部类不会加载,只有调用getInstance方法时,才会加载(实现延时加载)
	private static class SingletonClassInstance {
		private final static SingletonDemo04 instance = new SingletonDemo04();
	}

	private SingletonDemo04() {
	}

	// 线程安全,方法不同步,调用效率提高
	public static SingletonDemo04 getInstance() {
		return SingletonClassInstance.instance;
	}
}

  枚举式:

/**
 * 单例模式:枚举类型实现单例模式 线程安全,调用效率高。但是,不能延时加载 避免反射和反序列化的漏洞
 * 
 * @author cookie
 * 
 */
public enum SingletonDemo05 {
	INSTANCE;// 这个枚举元素,本身就是单例模式
	// 添加自己需要的操作
	public void singletonOperation() {

	}

}

  下面是测试5种单例模式的效率:

/**
 * 
 * 描述:多线程环境下五种单例模式的效率
 * @author cookie
 */
public class Client2 {

	/**
	 * @param args
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) throws InterruptedException {
		long start = System.currentTimeMillis();
		int threadNum = 10;
		final CountDownLatch countDownLatch = new CountDownLatch(threadNum);
		//10个线程
		for (int i = 0; i < threadNum; i++) {

			new Thread(new Runnable() {
				@Override
				public void run() {
					for (int i = 0; i < 100000; i++) {
						SingletonDemo05 s1 = SingletonDemo05.INSTANCE;
					}
					countDownLatch.countDown();//计数器减一
				}
			}).start();
		
		}
		countDownLatch.await();//main线程阻塞,等待计数器为0,即threadNum = 0;
		long end = System.currentTimeMillis();
		System.out.println("总耗时:"+(end-start));
	}

}

  实现结果如下:

单例模式 总耗时
饿汉式 13
懒汉式 547
双重检测锁式 20
静态内部类式 17
枚举式 13

 选用时,

  单例对象,占用资源少,无需延时加载,枚举式 优于 饿汉式

  单例对象,占用资源多,需要延时加载,静态内部类式 优于 懒汉式



原文地址:https://www.cnblogs.com/blogofcookie/p/5793865.html