单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。
如何实现?
- 单例类,私有化构造器。
- 在类的内部创建一个类的实例。
- 通过方法来返回实例。
例子:
饿汉式
//单例类-饿汉式
class Singleton{
//私有化构造方法,使其不可以在类的外部创建该类的对象。
private Singleton(){}
//实例化一个对象。
private static Singleton singleton=new Singleton();
//提供静态方法,外部通过类名调用。
public static Singleton getSingleton(){
return singleton;
}
}
懒汉式:存在线程安全问题。
//单例类-懒汉式:多并发情况下 存在线程安全问题。
class Singleton1{
private Singleton1(){}
private static Singleton1 singleton1;
public static Singleton1 getSingleton1(){
if(singleton1==null){
singleton1=new Singleton1();
}
return singleton1;
}
}
解决方案代码:
//懒汉式解决安全问题:
class Singleton2{
private Singleton2(){
}
private static Singleton2 instance;
public static Singleton2 getInstance(){
//第一次判断:当前实例为null,也就是实例还未创建时才进行同步,否则就直接返回,
//这样就节省了很多无谓的线程等待时间。
if(instance==null){
//使用同步代码块解决;对于静态方法,使用当前类本身当做锁。
synchronized (Singleton2.class) {
//第2次判断:如果在第一次判断时有A线程和B线程都在同步块外面判断了instance为null,
//结果A线程首先获得了线程锁,进入了同步块,然后A线程会创造一个实例。
//此时instance已经被赋予了实例,A线程退出同步代码块,直接返回了第一个创造的实例。
//此时B线程获得线程锁,也进入同步块,此时A线程其实已经创造好了实例,B线程正常情况应该直接返回的,
//但是因为同步块里没有判断是否为null,直接就是一条创建实例的语句,所以B线程也会创造一个实例返回,
//此时就造成创造了多个实例的情况。
if (instance == null) {
instance = new Singleton2();
}
}}
return instance;
}
}
jdk中的runtime单例类: