四,单例模式

来源:互联网 发布:淘宝上什么活动给力 编辑:程序博客网 时间:2024/06/16 12:14

1 单例模式

单例模式确保某个类只有一个实例,而且实例并向整个系统提供这个实例。

单例模式的三个特点:

  • 单例类只能有一个实例
  • 单例类必须要自行创建这个实例
  • 单例类需要向整个系统提供这个实例

单例模式中还存在着两种设计模式

  1. 饿汉式的单例模式
  2. 懒汉式的单例模式

2 饿汉式的单例模式

package com.designpattern.singleton;/** * Created by Administrator on 2016/9/20. */public class EagerSingleton {    private static final EagerSingleton eagerSingleton = new EagerSingleton();    private EagerSingleton(){    }    public static EagerSingleton getInstance(){        return eagerSingleton;    }    public static void main(String args[]){        EagerSingleton eagerSingleton1 = EagerSingleton.getInstance();        EagerSingleton eagerSingleton2 = EagerSingleton.getInstance();        System.out.println(eagerSingleton1==eagerSingleton2);    }}

这种模式下线程是安全的,不会出现延迟加载而导致产生不同的实例对象。上面是采用静态常量的形式,代码也可以使用静态代码块的形式。静态代码块的形式如下:

package com.designpattern.singleton;/** * Created by Administrator on 2016/9/20. */public class EagerSingleton {    private static final EagerSingleton eagerSingleton;    static {        eagerSingleton = new EagerSingleton();    }    private EagerSingleton(){    }    public static EagerSingleton getInstance(){        return eagerSingleton;    }    public static void main(String args[]){        EagerSingleton eagerSingleton1 = EagerSingleton.getInstance();        EagerSingleton eagerSingleton2 = EagerSingleton.getInstance();        System.out.println(eagerSingleton1==eagerSingleton2);    }}

3 懒汉式的单例模式

懒汉式的单例模式是线程不安全的,如果在多线程下,一个线程进入了if (lazySingleton == null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以在多线程环境下不可使用这种方式。

package com.designpattern.singleton;/** * Created by Administrator on 2016/9/20. */class LazySingleton {    private static LazySingleton lazySingleton = null;    private LazySingleton(){    }    public static LazySingleton getInstance(){        if(lazySingleton == null){            try {                Thread.sleep(100);            } catch (InterruptedException e) {                e.printStackTrace();            }            lazySingleton = new LazySingleton();        }        return lazySingleton;    }}class LazySigletonThread implements Runnable{    @Override    public void run() {        System.out.println(LazySingleton.getInstance());    }    public static void main(String[] args) {        LazySigletonThread lazySigletonThread1 = new LazySigletonThread();        LazySigletonThread lazySigletonThread2 = new LazySigletonThread();        Thread thread1 = new Thread(lazySigletonThread1);        Thread thread2 = new Thread(lazySigletonThread2);        thread1.start();        thread2.start();    }}

执行结果会出现不同的实例对象,这样单例模式就失去存在的意义。

com.designpattern.singleton.LazySingleton@24189895com.designpattern.singleton.LazySingleton@2e24a61e

但是如果在给getInstance()方法加上synchronized机制,这样就不会出现两个不同的实体类对象了。

    synchronized public static LazySingleton getInstance(){        if(lazySingleton == null){            try {                Thread.sleep(100);            } catch (InterruptedException e) {                e.printStackTrace();            }            lazySingleton = new LazySingleton();        }        return lazySingleton;    }

4 采用静态内部类的形式实现单例模式

public class Singleton {    private Singleton() {}    private static class SingletonInstance {        private static final Singleton INSTANCE = new Singleton();    }    public static Singleton getInstance() {        return SingletonInstance.INSTANCE;    }}

这种方式跟饿汉式方式采用的机制类似,但又有不同。两者都是采用了类装载的机制来保证初始化实例时只有一个线程。不同的地方在饿汉式方式是只要Singleton类被装载就会实例化,没有Lazy-Loading的作用,而静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化。
类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。

0 0
原创粉丝点击