设计模式 | 单例模式
Posted 数据与共享
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式 | 单例模式相关的知识,希望对你有一定的参考价值。
“ 单例,即:只有一个实例。 通过单例模式可以保证,一个系统或应用中, 类的实例只有一个。通过使用单例模式,减小了系统的开销,并且有利于Java垃圾回收。”
1.懒汉模式
缺点:许多博客中说,多线程下会有异常发生,可是经过我的测试,并没有发现异常情况。
实例类:SingleExample
1private static SingleExample singleExample = null;
2private static int i = 0;
3private SingleExample() {
4}
5public static SingleExample getInstance() {
6 if (singleExample == null) {
7 i++;
8 System.out.println("i=" + i);
9 singleExample = new SingleExample();
10 }
11 return singleExample;
12}
测试类:
1public static void main(String[] args) {
2 SingleExample single = SingleExample.getInstance();
3 SingleExample single2 = SingleExample.getInstance();
4 SingleExample single3 = SingleExample.getInstance();
5}
Test测试输出:i = 1;说明三次调用只创建了一个对象。单例模式实现。
懒汉模式 多线程举例:
实例类:SingleThread
1private static SingleThread single;
2private static int i = 0;
3private SingleThread() {
4}
5public static SingleThread getSingle() {
6 if (single == null) {
7 i++;
8 System.out.println("i=" + i);
9 single = new SingleThread();
10 }
11 return single;
12}
13@Override
14public void run() {
15 // TODO Auto-generated method stub
16}
测试方法:
1public static void main(String[] args) {
2 SingleThread single1 = SingleThread.getSingle();
3 SingleThread single2 = SingleThread.getSingle();
4 SingleThread single3 = SingleThread.getSingle();
5 SingleThread single4 = SingleThread.getSingle();
6 Thread thread1 = new Thread(single1);
7 Thread thread2 = new Thread(single2);
8 Thread thread3 = new Thread(single1);
9 Thread thread4 = new Thread(single2);
10 thread1.start();
11 thread2.start();
12 thread3.start();
13 thread4.start();
14}
Test测试输出:i = 1;说明三次调用只创建了一个对象。单例模式实现。多线程下也是安全的,或者我的测试方法不对,希望大家集思广益,指出我的错误之处。
2.饿汉模式
类在装载时就进行了实例化,这一点不如懒汉模式。
实例类:HungryPattern
1private static HungryPattern hunPattern = new HungryPattern();
3private HungryPattern() {
4}
5public static HungryPattern getHunPattern() {
8 return hunPattern;
9}
3.静态内部类
实例类:StaticInnerClass
1private StaticInnerClass() {
2}
3private static class SinglePattern {
4 private static final StaticInnerClass singlePa = new StaticInnerClass();
5}
6public static final StaticInnerClass getInnerClass() {
7 return SinglePattern.singlePa;
8}
4.双重检查
Double Check
实例类:DoubleCheck
1private static volatile DoubleCheck doubleCheck;
2private DoubleCheck() {
3};
4public static DoubleCheck getIntance() {
5 if (doubleCheck == null) {
6 synchronized (DoubleCheck.class) {
7 if (doubleCheck == null) {
8 doubleCheck = new DoubleCheck();
9 }
10 }
11 }
12 return doubleCheck;
13}
14@Override
15public void run() {
16 // TODO Auto-generated method stub
17}
5.enum实现单例模式
为什么用枚举:
(1)enum 继承自Enum,而Enum是被final修饰的类。
(2)final修饰,这意味着其本身就是一个单例类型,并且其线程安全。
(3)并且其实现过程简单,代码的可读性更强。
实例类:Instance1
1public static void show() {
2 System.out.println("我是Instance1");
3}
枚举类:Instance
1instance;
2private Instance1 ins1 = new Instance1();
3public Instance1 getInstance() {
4 return ins1;
5}
测试类:TestInstance,运行结果为ture。
1public static void main(String[] args) {
2 Instance1 ins1 = Instance.instance.getInstance();
3 Instance1 ins2 = Instance.instance.getInstance();
4 System.out.println(ins1==ins2);
5}
使用enum有没有很爽,我这个例子可能没有体现出线程安全,代码简洁等特性。但是请相信我,越来越多的人会发现enum是多么好用,而static final这种机械写法是如何的冗杂。我司使用enum的频率已成上升趋势。
说明:单例模式的u构造很简单,但是在合适的应用场景使用有点不知所措,尤其是设计多线程时。另外我终于忍不了AV画质的截图,使用了Md2All工具对代码进行了整理。
以上是关于设计模式 | 单例模式的主要内容,如果未能解决你的问题,请参考以下文章