一、饿汉式(线程安全,调用效率高,但是不能延时加载)
JAVA例子:
public class Test {
private static Test test = new Test();
private Test() {}
public static Test getInstance() {
return test;
}
// 忽略方法printTest(),仅用来输出
public void printTest() {
System.out.println("maisomgan:java-test");
}
}
Kotlin例子:
object Test1 {
// 忽略方法printTest(),仅用来输出
fun printTest() {
println("maisomgan:kotlin-test")
}
}
在Kotlin代码类型中进行调用:
Test.getInstance().printTest()
Test1.printTest()
输出结果:
二、懒汉式(线程安全,调用效率不高,但是能延时加载)
Java例子:
public class Test {
private static Test test;
private Test() {}
public static Test getInstance() {
if (test == null) {
test = new Test();
}
return test;
}
// 忽略方法printTest(),仅用来输出
public void printTest() {
System.out.println("maisomgan:java-test");
}
}
Kotlin例子:
class Test1 private constructor() {
companion object {
private var test1: Test1? = null
get() {
if (field == null) {
field = Test1()
}
return field
}
fun getInstance(): Test1 {
return test1!!
}
}
// 忽略方法printTest(),仅用来输出
fun printTest() {
println("maisomgan:kotlin-test")
}
}
在Kotlin代码类型中进行调用:
Test.getInstance().printTest()
Test1.getInstance().printTest()
输出结果:
三、线程安全的懒汉式
Java例子:
public class Test {
private static Test test;
private Test() {}
public static synchronized Test getInstance() {
if (test == null) {
test = new Test();
}
return test;
}
// 忽略方法printTest(),仅用来输出
public void printTest() {
System.out.println("maisomgan:java-test");
}
}
Kotlin例子:
class Test1 private constructor() {
companion object {
private var test1: Test1? = null
get() {
if (field == null) {
field = Test1()
}
return field
}
@Synchronized
fun getInstance(): Test1 {
// !!表示该属性一定不能为Null,否则将抛出空指针异常错误导致crash
return test1!!
}
}
// 忽略方法printTest(),仅用来输出
fun printTest() {
println("maisomgan:kotlin-test")
}
}
在Kotlin代码类型中进行调用:
Test.getInstance().printTest()
Test1.getInstance().printTest()
输出结果:
四、双重校验锁式双重锁判断机制(由于JVM底层模型原因,偶尔会出问题,不建议使用)
Java例子:
public class Test {
// volatile关键字保证了test成员变量的可见性,一定程度上保护了线程的安全
// new 操作不是原子操作,在 JVM 层面会导致重排序
// volatile在此主要是禁止重排序(synchronized只能保证有序性却不能禁止重排序)
private volatile static Test test;
private Test() {}
public static Test getInstance() {
if (test == null) {
synchronized (Test.class) {
if (test == null) {
test = new Test();
}
}
}
return test;
}
// 忽略方法printTest(),仅用来输出
public void printTest() {
System.out.println("maisomgan:java-test");
}
}
Kotlin例子:
class Test1 private constructor() {
companion object {
// lazy是Kotlin的延迟属性
val test1: Test1 by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
Test1()
}
}
// 忽略方法printTest(),仅用来输出
fun printTest() {
println("maisomgan:kotlin-test")
}
}
在Kotlin代码类型中进行调用:
Test.getInstance().printTest()
Test1.test1.printTest()
输出结果:
五、静态内部类式(线程安全,调用效率高,可以延时加载)
Java例子:
public class Test {
private static class Singleton {
private static Test test = new Test();
}
private Test() {}
public static Test getInstance() {
return Singleton.test;
}
// 忽略方法printTest(),仅用来输出
public void printTest() {
System.out.println("maisomgan:java-test");
}
}
Kotlin例子:
class Test1 private constructor() {
companion object {
val test1 = Singleton.singleton
}
private object Singleton {
val singleton = Test1()
}
// 忽略方法printTest(),仅用来输出
fun printTest() {
println("maisomgan:kotlin-test")
}
}
在Kotlin代码类型中进行调用:
Test.getInstance().printTest()
Test1.test1.printTest()
输出结果:
六、枚举类实现单例(线程安全,调用效率高,不能延时加载,可以天然的防止反射和反序列化调用)
Java例子:
public enum Test {
// 枚举元素本身就是单例
INSTANCE;
// 忽略方法printTest(),仅用来输出
public void printTest() {
System.out.println("maisomgan:java-test");
}
}
Kotlin例子:
enum class Test1 {
// 枚举元素本身就是单例
INSTANCE;
// 忽略方法printTest(),仅用来输出
fun printTest() {
println("maisomgan:kotlin-test")
}
}
在Kotlin代码类型中进行调用:
Test.INSTANCE.printTest()
Test1.INSTANCE.printTest()
输出结果:
如何选用:
- 单例对象 占用资源少,不需要延时加载,枚举 好于 饿汉
- 单例对象 占用资源多,需要延时加载,静态内部类 好于 懒汉式