单线程Singleton
package cn.chen.design;
public class Singleton {
private Singleton(){}
private static Singleton instance;
public static Singleton getInstance(){
if(instance == null) instance = new Singleton();
return instance;
}
}
多线程安全的Singleton
1.加锁
package cn.chen.design;
public class Singleton {
private Singleton(){}
private static Singleton instance;
public static synchronized Singleton getInstance(){
if(instance == null) instance = new Singleton();
return instance;
}
}
这个方法只是在instance为null的时候,会有并发问题,如果instance已经创建,就不会有线程安全问题,但是每次为一个只读的方法加一个锁,性能上划不来
2.静态内部类
package cn.chen.design;
public class Singleton2 {
private Singleton2(){}
private static class SingletonWrapper{
static Singleton2 instance = new Singleton2();
}
public static Singleton2 getInstance(){
return SingletonWrapper.instance;
}
}
当有线程第一次调用getInstance的时候,SIngletonWrapper就会被class loader加载进JVM,在加载的同时执行instance的初始化。
类的加载过程是单线程执行。它的并发安全是由JVM保证的。所以,这样写的好处实在instance初始化的过程中,由JVM的类加载机制保证了线程安全,而在初始化完成之后,不管后面多少次调用getInstance方法都不会遇到锁的问题。
3.枚举
package cn.chen.design;
public enum Singleton3 {
INSTANCE;
public void say(){
System.out.println("hello instance");
}
}
class Main{
public static void main(String[] args) {
Singleton3.INSTANCE.say();
}
}
在加载Singleton的时候,就要把instance初始化完成。这仍然利用了加载器是线程安全的这一特性。
(不要使用双重检查实现Singleton)