单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
- 单例类只能有一个实例。
- 单例类必须自己自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例。
饿汉模式
public class Singleton {
//private 私有
private static Singleton instance = new Singleton();
//private 私有
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
懒汉式(非线程安全)
public class Singleton {
private static Singleton instance;
private Singleton (){
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
懒汉式(线程安全)
public class Singleton {
private static Singleton instance;
private Singleton (){
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
双重校验锁(DCL)
public class Singleton {
/**
* 注意此处使用的关键字 volatile,
* 被volatile修饰的变量的值,将不会被本地线程缓存,
* 所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。
*/
private volatile static Singleton singleton;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return singleton;
}
}
静态内部类
public class Singleton {
private Singleton(){
}
public static Singleton getInstance(){
return SingletonHolder.sInstance;
}
private static class SingletonHolder {
private static final Singleton sInstance = new Singleton();
}
}
使用容器
public class SingletonManager {
private static Map<String, Object> objMap = new HashMap<String,Object>();
private Singleton() {
}
public static void registerService(String key, Objectinstance) {
if (!objMap.containsKey(key) ) {
objMap.put(key, instance) ;
}
}
public static ObjectgetService(String key) {
return objMap.get(key) ;
}
}
Volatile可以看做是轻量级的 Synchronized,它只保证了共享变量的可见性。在线程 A 修改被 volatile 修饰的共享变量之后,线程 B 能够读取到正确的值。java 在多线程中操作共享变量的过程中,会存在指令重排序与共享变量工作内存缓存的问题。
public class single {
public static void main (String[] args) {
singleton sin1 = singleton.getSingle();
singleton sin2 = singleton.getSingle();
System.out.println(sin1 == sin2);
Singleton2 sin3 = Singleton2.getInstance();
Singleton2 sin4 = Singleton2.getInstance();
System.out.println(sin3 == sin4);
}
}
//饿汉式。类一加载对象就创建单例对象
class singleton{
private static singleton sin = new singleton();
private singleton() {};
public static singleton getSingle() {
return sin;
}
}
//懒汉式,即延迟加载。单例在第一次调用 getInstance() 方法时才实例化,在类加载时并不自动实例化,在需要的时候再进行加载实例。
class Singleton2 {
private Singleton2(){}
private static Singleton2 instance = null;
public static Singleton2 getInstance(){
if(instance == null){
instance = new Singleton2();
}
return instance;
}
}
//多线程处理创建单例是一起的,用排队,避免如果使用懒汉式的方式创建单例对象,那就可能会出现创建多个实例的情况,添加Synchronized实现线程安全
//不过,在多线程中很好的工作而且是线程安全的,但是每次调用 getInstance() 方法都需要进行线程锁定判断,在多线程高并发访问环境中,将会导致系统性能下降。事实上,不仅效率很低,99%情况下不需要线程锁定判断。
class Singleton3 {
private Singleton3(){}
private static Singleton3 instance = null;
public static synchronized Singleton3 getInstance(){
if(instance == null){
instance = new Singleton3();
}
return instance;
}
}
//过双重校验锁的方式进行处理。换句话说,利用双重校验锁,第一次检查是否实例已经创建,如果还没创建,再进行同步的方式创建单例对象。
class Singleton4 {
private Singleton4(){}
private static Singleton4 instance = null;
public static Singleton4 getInstance(){
if(instance == null){
synchronized(Singleton4.class){
if(instance == null){
instance = new Singleton4();
}
}
}
return instance;
}
}
//静态内部类
class Singleton5{
private Singleton5() {}
private static class SingletonHolder{
private final static Singleton5 instance = new Singleton5();
}
public static Singleton5 getInstance() {
return SingletonHolder.instance;
}
}