单例模式
单例模式是比较常用和容易理解的一种设计模式,目的是一个单例对象的类只允许存在一个实例。
常用的例如数据库连接池和多线程的线程池就是单例模式的。
单例模式的几种实现方式:
饿汉模式:
/**
* Created by j on 2018/3/1.
*/
public class
Singleton {
private static
Singleton
ourInstance
=
new
Singleton()
;
public static
Singleton
getInstance
() {
return
ourInstance
;
}
private
Singleton
() {}
}
这种方式 因为定义实例为静态的,所以在虚拟机对该类进行装载的时候就会生成实例。属于常用的方式,但是缺点在于如果不需要调用该实例会对内存造成浪费。
非线程安全-懒汉模式:
/**
* Created by j on 2018/3/1.
*/
public class
Singleton {
public static
Singleton
singleton
;
public static
Singleton
getInstance
() {
if
(
singleton
==
null
) {
singleton
=
new
Singleton()
;
}
return
singleton
;
}
private
Singleton
() {}
}
顾名思义,就是在不需要该实例的时候不创建,只有在第一次用到的时候会创建该实例,但是此方式不建议使用,因为是非线程安全的,如果多线程同时获取实例,并且在同时验证实例为空时通过,会创建两个实例。
线程安全-同步-懒汉模式:
public class
Singleton {
public static
Singleton
singleton
;
public static synchronized
Singleton
getInstance
() {
if
(
singleton
==
null
) {
singleton
=
new
Singleton()
;
}
return
singleton
;
}
private
Singleton
() {}
}
在获取对象的实例方法上通过synchronized关键字为该方法添加同步锁,这样可以保证只有一个线程会调用该方法,但是如果多线程同时过来时就会发生线程堵塞,造成效率性能的极度下降,所以不建议采用此方式。
非线程安全-同步代码块-懒汉模式:
/**
* Created by j on 2018/3/1.
*/
public class
Singleton {
public static
Singleton
singleton
;
public static
Singleton
getInstance
() {
if
(
singleton
==
null
) {
synchronized
(Singleton.
class
){
singleton
=
new
Singleton()
;
}
}
return
singleton
;
}
private
Singleton
() {}
}
当多个线程同时进入到null判断之后,虽然锁的是代码块,但是还会执行两次实例化。
双重检查模式
/**
* Created by j on 2018/3/1.
*/
public class
Singleton {
public static
Singleton
singleton
;
public static
Singleton
getInstance
() {
if
(
singleton
==
null
) {
synchronized
(Singleton.
class
) {
if
(
singleton
==
null
) {
singleton
=
new
Singleton()
;
}
}
}
return
singleton
;
}
private
Singleton
() {}
}
这样可以保证是线程安全的。
静态内部类模式
/**
* Created by j on 2018/3/1.
*/
public class
Singleton {
private
Singleton
() {}
private static class
SingletonIns{
private static final
Singleton
instance
=
new
Singleton()
;
}
public static
Singleton
getInstance
() {
return
SingletonIns.
instance
;
}
}
这样与饿汉模式相似,该模式是懒加载模式,饿汉模式在类被装载时创建实例,而该模式,只有在调用getInstance时才会装载静态内部类,然后创建实例。