单例模式是软件设计模式中最常用的一种设计模式,他的理解为一个类只能存在一个实例的存在。
单例设计模式通常可以有多种实现方法,最常使用的是饿汉式即立即加载,与懒汉式(懒加载)两种方法。
实现思路:就是构造方法私有,其他类就不能直接通过new关键字去创建该类的对象,提供一个静态方法用于创建该类的唯一对象。
首先先说说饿汉式单例模式,所谓饿汉式,用大白话说就是很饿,看见什么都想吃,可以这样子形容他。在Java中的表现,就是类加载完,此类的对象就会被立即加载到堆中。
public class Single { private static Single single=new Single(); private Single(){} public static Single getInstance(){ return single; } }
这种模式的弊端,会浪费堆的空间,因为没有使用到该类的对象,如果是加载大量的资源,就会造成资源的过度浪费。所以懒汉式是在这个基础上进行优化。不会一开始就加载,是该对象什么时候被使用到才加载。
懒汉式单例模式
这种模式作用是延迟加载,懒加载,都可以这样子理解。
public class LazyMan { private static LazyMan lazyMan; private LazyMan(){ System.out.println(Thread.currentThread().getName()); } public static LazyMan getInstance(){ if (lazyMan==null){ lazyMan = new LazyMan(); } return lazyMan; } }
但是这个代码有一个问题,这种情况下只能是在单线程的时候安全,如果是多线程的情况下,会出现多个实例的可能。因为没有锁的情况下,一个线程在if (lazyMan==null) 这个判断的时候,其他线程也可能在进行判断,从而导致多个实例的情况。
public class LazyMan { private static LazyMan lazyMan; private LazyMan(){ System.out.println(Thread.currentThread().getName()); } public static LazyMan getInstance(){ if (lazyMan==null){ lazyMan = new LazyMan(); } return lazyMan; } //并发情况下,会存在多个实例 public static void main(String[] args) { for (int i = 0; i < 10; i++) { new Thread(()->{ LazyMan.getInstance(); }).start(); } } }
并发情况下,测试如下