1. 概念
- 保证一个类只有一个实例
- 并为该实例提供一个全局唯一的访问节点
2. 懒汉式-方式一
2.1 代码示例(方式一)
示例
java
public class Singleton03 {
/**
* 构造器私有化
*/
private Singleton03() {
}
/**
* 成员变量
*/
private static Singleton03 INSTANCE;
/**
* 对外提供公有的静态方法
*/
public static Singleton03 getInstance() {
// 用到才加载
if (INSTANCE == null) {
INSTANCE = new Singleton03();
}
return INSTANCE;
}
}
java
public class SingletonTest03 {
public static void main(String[] args) {
Singleton03 instance = Singleton03.getInstance();
Singleton03 instance1 = Singleton03.getInstance();
System.out.println(instance == instance1);
System.out.println("instance.hashCode= " + instance.hashCode());
System.out.println("instance1.hashCode= " + instance1.hashCode());
}
}
2.2 优缺点(方式一)
- 起到了Lazy Loading的效果,但是只能在单线程下使用。
- 如果在多线程下,一个线程进入了if(singleton==null)判断语句块,还未来得及
往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以
在多线程环境下不可使用这种方式。
2.3 结论(方式一)
- 线程不安全,在实际开发中,不要使用这种方式。
3. 懒汉式-方式二
3.1 代码示例(方式二)
示例
java
public class Singleton04 {
/**
* 构造器私有化
*/
private Singleton04() {
}
/**
* 成员变量
*/
private static Singleton04 INSTANCE;
/**
* 对外提供公有的静态方法
*/
public static synchronized Singleton04 getInstance() {
// 加入同步代码,解决线程不安全问题
if (INSTANCE == null) {
INSTANCE = new Singleton04();
}
return INSTANCE;
}
}
java
public class SingletonTest04 {
public static void main(String[] args) {
Singleton04 instance = Singleton04.getInstance();
Singleton04 instance1 = Singleton04.getInstance();
System.out.println(instance == instance1);
System.out.println("instance.hashCode= " + instance.hashCode());
System.out.println("instance1.hashCode= " + instance1.hashCode());
}
}
3.2 优缺点(方式二)
- 解决了线程不安全问题。
- 效率太低了,每个线程在想获得类的实例时候,执行getinstance()方法都要进行同步。而其实这个方法只执行一次实例化代码就够了,后面的想想获得该类实例,直接return就行了。方法进行同步效率太低。
3.3 结论(方式二)
- 线程安全,但效率太低,在实际开发中,不推荐使用这种方式。
4. 懒汉式-方式三
4.1 代码示例(方式三)
示例
java
public class Singleton05 {
private Singleton05() {}
private static Singleton05 INSTANCE;
public static Singleton05 getInstance() {
if (INSTANCE == null) {
synchronized (Singleton05.class) {
INSTANCE = new Singleton05();
}
}
return INSTANCE;
}
}
java
public class SingletonTest05 {
public static void main(String[] args) {
Singleton05 instance = Singleton05.getInstance();
Singleton05 instance1 = Singleton05.getInstance();
System.out.println(instance == instance1);
System.out.println("instance.hashCode= " + instance.hashCode());
System.out.println("instance1.hashCode= " + instance1.hashCode());
}
}
4.2 优缺点(方式三)
- 这种方式,本意是想对第四种实现方式的改进,因为前面同步方法效率太低,改为同步产生实例化的的代码块。
- 但是这种同步并不能起到线程同步的作用。跟方式一实现方式遇到的情形一致,假如一个线程进入了if(singleton==null)判断语句块,还未来来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。
4.3 结论(方式三)
- 线程不安全,在实际开发中,不要使用这种方式