线程不安全的实现方式
package com.sheby.hfdpkt.chap05.singleton
import kotlin.concurrent.thread
/**
* 线程不安全的单例:传统方法
*/
class ThreadNotSafeSingleton private constructor() {
init {
println("ThreadNotSafeSingleton")
}
companion object {
private var singleton: ThreadNotSafeSingleton? = null
get() {
if (field == null) {
field = ThreadNotSafeSingleton()
}
return field
}
@JvmStatic
fun getInstance(): ThreadNotSafeSingleton {
return singleton!!
}
}
}
fun main() {
thread {
println("thread ${ThreadNotSafeSingleton.getInstance()}")
}
println("main ${ThreadNotSafeSingleton.getInstance()}")
}
《head first 设计模式》中对于单例有三种线程安全的实现方式
1.直接同步getInstance()方法,
肯定线程安全,但会有性能问题;
package com.sheby.hfdpkt.chap05.singleton
import kotlin.concurrent.thread
/**
* 线程安全的单例
* 使用锁
*/
class ThreadSafeSingleton private constructor() {
init {
println("ThreadSafeSingleton")
}
companion object {
private var singleton: ThreadSafeSingleton? = null
@JvmStatic
@Synchronized
fun getInstance(): ThreadSafeSingleton {
if (singleton == null) {
singleton = ThreadSafeSingleton()
}
return singleton!!
}
}
}
fun main() {
thread {
println("thread ${ThreadSafeSingleton.getInstance()}")
}
println("main ${ThreadSafeSingleton.getInstance()}")
}
2.在getInstance()中双重检查加锁,
只有单例未创建之前才会进入锁的代码块,减少不必要的同步次数,提高性能;
package com.sheby.hfdpkt.chap05.singleton
import kotlin.concurrent.thread
/**
* 线程安全的单例
* 使用双重检查加锁的方法:只适用于jdk5之后的
*/
class DoubleCheckSingleton private constructor() {
init {
println("DoubleCheckSingleton")
}
companion object {
@Volatile
private var sSingleton: DoubleCheckSingleton? = null
// get() {
// if (field == null) {
// synchronized(DoubleCheckSingleton::class) {
// if (field == null) {
// field = DoubleCheckSingleton()
// }
// }
// }
// return field
// }
@JvmStatic
fun getInstance(): DoubleCheckSingleton {
if (sSingleton == null) {
synchronized(DoubleCheckSingleton::class) {
if (sSingleton == null) {
sSingleton = DoubleCheckSingleton()
}
}
}
return sSingleton!!
}
}
}
fun main() {
thread {
println("thread ${DoubleCheckSingleton.getInstance()}")
}
println("main ${DoubleCheckSingleton.getInstance()}")
}
3.使用饿汉模式(急切实例化),
直接创建出该对象,但这样在没有使用到该对象之前,提前创建会多多少少浪费资源;
package com.sheby.hfdpkt.chap05.singleton
import kotlin.concurrent.thread
/**
* 饿汉模式的单例:线程安全
*/
class HungrySingleton private constructor() {
init {
println("HungrySingleton")
}
companion object {
private var singleton = HungrySingleton()
@JvmStatic
fun getInstance(): HungrySingleton {
return singleton
}
}
}
fun main() {
// TODO: 理论上 要先打印 "HungrySingleton"再打印 "main--"的
// 可能是kotlin 编译出来的多了个HungrySingletonKt.class,而这main函数在这个类里面
println("main--")
thread {
println("thread ${HungrySingleton.getInstance()}")
}
println("main ${HungrySingleton.getInstance()}")
}
此外还有java的静态内部类实现的单例,kotlin版本
package com.sheby.hfdpkt.chap05.singleton
import kotlin.concurrent.thread
/**
*相当于JAVA的静态内部类单例
* 参考自
* https://blog.csdn.net/qq_40987010/article/details/122499694
*/
class InnerSingleton private constructor() {
init {
println("InnerSingleton")
}
private object InnerHolder {
val singleton = InnerSingleton()
}
companion object {
@JvmStatic
fun getInstance(): InnerSingleton {
return InnerHolder.singleton
}
}
}
fun main() {
thread {
println("thread ${InnerSingleton.getInstance()}")
}
println("main ${InnerSingleton.getInstance()}")
}
最后当然少不了kotlin自带的object关键字 的单例模式
如果构造方法没有参数,使用这种方式是最简单的
package com.sheby.hfdpkt.chap05.singleton
import kotlin.concurrent.thread
object KotlinSingleton {
init {
println("create KotlinSingleton ${Thread.currentThread().name}}")
Thread.sleep(200)
}
}
fun main() {
thread {
println("thread $KotlinSingleton")
}
println("main $KotlinSingleton")
}
网友评论