写在前面
单例Singleton设计模式, 老生常谈的一个设计模式。但你真的用对了么? 用的姿势很重要!
1.概念解释
单例顾名思义就是只产生一个实例对象。那怎样保证单一呢?把目标类提供给外部创建实例对象的能力收回,即构造函数设为私有,然后内部提供一个生成实例静态方法。设计成单例模式, 有各种各样的实现方式。
2.单例模式的设计
2.1 饿汉式单例
饿汉式单例是指在方法调用前,实例就已经创建好了。
-实现代码:
public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance() { return instance; }}
-验证高并发下的执行情况
public class SingletonClient { public static void main(String[] args) throws InterruptedException { Thread[] threads = new Thread[10]; for (int i = 0; i < 10; i++) { final Singleton instance = Singleton.getInstance(); threads[i] = new Thread(new Runnable() { @Override public void run() { System.out.println(instance.hashCode()); } }); } for (Thread thread : threads) { thread.start(); } }}
- 结果
165827088165827088165827088165827088165827088165827088165827088165827088165827088165827088
2.2 懒汉式单例
懒汉式单例是指在方法调用获取实例时才创建实例,因为相对饿汉式显得“不急迫”,所以被叫做“懒汉模式”。
1)单线程的懒汉式单例 -- 初学者最容易犯错的写法.
public class Singleton { private static Singleton instance = null; private Singleton() { } public static Singleton getInstance() { if (instance == null) { try { // 刻意模仿多线程访问下创建实例不是单一的情况 Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } instance = new Singleton(); } return instance; }}
上面创建单例在单线程下是木问题的。但在多线程访问下就会有问题啦。
如何改进呢?来,再往下看2)线程安全的懒汉式单例.
-同步方法锁定
同步方法效率很低, 它把真个方法都加了锁, 在高并发下, 只允许一个线程进入到该方法public class Singleton { private static Singleton instance = null; private Singleton() { } public synchronized static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }}
-同步代码块锁定
同步代码块效率也很低,但比同步方法效率高点, 它把高并发的代码块加了锁, 在高并发下, 只允许一个线程进入到该代码块。public class Singleton { private static Singleton instance = null; private Singleton() { } public static Singleton getInstance() { try { synchronized (Singleton.class) { if (instance == null) { Thread.sleep(100); instance = new Singleton(); } } } catch (Exception e) { } return instance; }}
-双检查锁机制(推荐)
这种方式不仅能保证线性安全, 还能提高效率。因为volatile关键字保证多线程间的可见性;在同步块中使用二次检查,以保证其不被重复实例化。集合其二者,这种实现方式既保证了其高效性,也保证了其线程安全性。public class Singleton { // volatile 关键词修饰 volatile private static Singleton instance = null; private Singleton() { } public static Singleton getInstance() { try { if (instance == null) { synchronized (Singleton.class) { Thread.sleep(100); instance = new Singleton(); } } } catch (Exception e) { } return instance; }}
3)使用静态内置类实现单例模式.
public class Singleton { private Singleton() { } private static class SingletonHandler { private static Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHandler.instance; }}
4)使用静态代码块实现单例模式
public class Singleton { private static Singleton instance; static { instance = new Singleton(); } private Singleton() { } public static Singleton getInstance() { return instance; }}
写在后面