单例模式应用于一个类只有一个实例的情况,并且为其实例提供一个全局的访问点。 特点: 1.一个类只有一个实例 2.自己创建这个实例 3.整个系统只能用这个实例 应用场景 外部资源:每台计算机有若干个打印机,但只能有一个PrinterSpooler,以避免两个打印作业同时输出到打印机。 内部资源:大多数软件都有一个(或多个)属性文件存放系统配置,这样的系统应该有一个对象管理这些属性文件。 实现方式 1.饿汉式:单例实例在类装载时就构建,急切初始化。(预先加载法) public class Singleton1 { private Singleton1() { } public static Singleton1 instance = new Singleton1(); public Singleton1 getInstance() { return instance; } }
2.懒汉式:单例实例在第一次被使用时构建,延迟初始化。 class Singleton2 { private Singleton2() { } public static Singleton2 instance = null; public static Singleton2 getInstance() { if (instance == null) { //多个线程判断instance都为null时,在执行new操作时多线程会出现重复情况 instance = new Singleton2(); } return instance; } } 懒汉式在单个线程中没有问题,但在多线程就可能会出现两个或多个Singleton2实例情况, 虽然后面实例化的Singleton2会覆盖前面实例化的Singleton2,但最好避免这样的情况。 改进方式就是加锁synchornized class Singleton3 { private Singleton3() { } public static Singleton3 instance = null; public static synchronized Singleton3 getInstance() { if (instance == null) { instance = new Singleton3(); } return instance; } }
class Singleton4 { private Singleton4() { } public static Singleton4 instance = null; public static Singleton4 getInstance() { if (instance == null) { synchronized (Singleton4.class) { if (instance == null) { instance = new Singleton4(); } } } return instance; } }
4.静态内部类 class Singleton5 { private Singleton5() { } private static class SingletonHelp { static Singleton5 instance = new Singleton5(); } public static Singleton5 getInstance() { return SingletonHelp.instance; } }
总结:一般采用饿汉式(1),若对资源十分在意可以采用静态内部类(4),不建议采用懒汉式及双重检测(2、3) 另外 对于第二种可以采用volatile方式 volatile用更低的代价代替同步 解释:同步的代价主要有覆盖范围决定,如果可以降低同步的覆盖范围,可大幅提升性能。 而volatile覆盖范围是变量级别的,因此同步代价很低。 volatile原理:告诉处理器,不要将其放入工作内存,而是直接在主存操作。因此,当多处理器或多线程在访问该变量时 都将直接操作主存,这在本质上做到了变量共享。 volation优势: 1.更大的程度吞吐量 2.更少的代码实现多线程 3.程序伸缩性好 4.比较好理解,无需太高的学习成本 volatile不足: 1.容易出问题 2.比较难设计 |
|
来自: binlingexia > 《java》