单例模式(kotlin实现)
2020-03-12 本文已影响0人
Merbng
/**kotlin 实现饿汉式单例
* Created by merbng on 2020/3/11.
*/
class SingletonDemo {
//1. kotlin 实现 饿汉式单例
object SingletonTest1 {
}
//2. kotlin 实现懒汉式单例
class SingletonTest private constructor() {
companion object {
private var instance: SingletonTest? = null
get() {
if (field == null) {
return SingletonTest()
} else {
return field
}
}
fun get(): SingletonTest {
return instance!!
}
}
}
// 3. 线程安全的 懒汉式
class SingletonTest2 private constructor() {
companion object {
private var instance: SingletonTest2? = null
get() {
if (field == null) {
return SingletonTest2()
} else {
return field
}
}
@Synchronized
fun get(): SingletonTest2 {
return instance!!
}
}
}
// 4. 双重校验锁 式
class SingletonTest3 private constructor() {
//lazy 是接受一个lambda并返回一个Lazy实例的函数,返回的实例可以作为延迟属性的委托:第一次调用get()会执行已传递lazy()的lambda表达式并记录结果,后续调用get()只是返回记录的结果
val instance: SingletonTest3 by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
SingletonTest3()
}
}
}
// 5.静态内部类式
class SingletonTest4 private constructor() {
companion object {
val instance = SingletonHolder.holder
}
object SingletonHolder {
val holder = SingletonTest4()
}
}
Java 实现
- 饿汉式
public class SingletonDemo{
private static SingletonDemo instance =new SingletonDemo();
private SingletonDemo(){};
public static SingletonDemo getInstance(){
return instance;
}
}
- 懒汉式
class SingletonDemo {
private SingletonDemo() {
}
private static SingletonDemo instance;
public static SingletonDemo getInstance() {
if (instance == null) {
return new SingletonDemo();
}
return instance;
}
}
- 线程安全的懒汉式
class SingletonDemo {
private SingletonDemo() {
}
private static SingletonDemo instance;
public static synchronized SingletonDemo getInstance() {//使用同步锁
if (instance == null) {
return new SingletonDemo();
}
return instance;
}
}
- 双重校验锁式(Double Check)
class SingletonDemo {
private SingletonDemo() {
}
private static volatile SingletonDemo instance;
public static SingletonDemo getInstance() {
if (instance == null) {
synchronized (SingletonDemo.class) {
if (instance == null) {
return new SingletonDemo();
}
}
}
return instance;
}
}
- 静态内部类式
class SingletonDemo5 {
private SingletonDemo5() {
}
private static class SingletonHolder {
private static SingletonDemo5 holder = new SingletonDemo5();
}
public static SingletonDemo5 getInstance() {
return SingletonHolder.holder;
}
}
双重校验锁的两个if判断有什么意义?
- 为何在synchronized外面判断?
为了提高性能,如果拿掉这次判断那么在执行的时候就会直接运行synchronized,所以会使每个getInstance()都会得到一个静态内部类,这样的话锁的获取以及释放的开销(包括上下文切换,内存同步等)都不可避免,降低了效率,所以在synchronized前面加一次判空,则会大大降低synchronized的执行次数 - 为何在synchronized内部还有执行一次判空?
因为可能会有多个线程一起进入同步块外的if,如果在同步块内不进行二次校验就会产生多个实例
在双重校验的情况下,保存实例的唯一静态变量要用volatile修饰,否则由于线程安全原因,一个类仍然会生成多个实例。
volatile
禁止指令重排序,保证多线程环境下的系统安全
被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存的,从而确保多个线程能正确的处理该变量。
参考链接