懒汉式(线程不安全)
【概念】
饿汉式使用静态变量或静态代码块的形式会导致直接产生不需要的类对象
懒汉式实现了懒加载形式(使用
getInstance()
时再创建)
【实验代码】
//懒汉式--线程不安全
public class Singleton03 {
public static void main(String[] args) {
SingleTon instance1 = SingleTon.getInstance();
System.out.println("instance1 值 = " + instance1.getValue());
instance1.setValue(8);
SingleTon instance2 = SingleTon.getInstance();
System.out.println("instance2 值 = " + instance2.getValue());
System.out.println("instance1 hashCode = " + instance1.hashCode());
System.out.println("instance2 hashCode = " + instance2.hashCode());
}
}
class SingleTon {
int value = 1;
private static SingleTon instance;
//1. 私有化Singleton类防止New
private SingleTon(){}
//2. 提供一个静态公有方法,当使用到该方法时,才创建 instance(懒汉式)
public static SingleTon getInstance(){
if(instance == null){
instance = new SingleTon();
}
return instance;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
【运行结果】
【优缺点】
- 实现了Lazy Loading的效果,但是只能在单线程下使用
- 如果使用多线程,一个线程进入了if ( singleton == null )判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以在多线程环境下不可使用这种方式
- 实际开发中:不可以使用这种方式
懒汉式(线程安全-同步方法)
【实验代码】
//懒汉式--同步方法
class Singleton04 {
public static void main(String[] args) {
SingleTon instance1 = SingleTon.getInstance();
System.out.println("instance1 值 = " + instance1.getValue());
instance1.setValue(8);
SingleTon instance2 = SingleTon.getInstance();
System.out.println("instance2 值 = " + instance2.getValue());
System.out.println("instance1 hashCode = " + instance1.hashCode());
System.out.println("instance2 hashCode = " + instance2.hashCode());
}
}
class SingleTon {
int value = 1;
private static SingleTon instance;
//1. 私有化Singleton类防止New
private SingleTon(){}
//2. 提供一个静态公有方法,使用synchronized同步锁住了getInstance方法 线程安全
//所有使用getInstance方法时都将同步等待
public static synchronized SingleTon getInstance(){
if(instance == null){
instance = new SingleTon();
}
return instance;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
【实验结果】
【优缺点】
- 解决了线程不安全的问题
- 效率过低。每个线程在想获得类的实例时,每次执行
getInstance()
方法都要进行同步。- 生成实例只需要保证生成一次实例化就足够了,后面获取该类实例,只需要return就行
- 实际开发:不推荐使用
懒汉式(线程不安全-同步代码块)
【实验代码】
package org.example.singledon.type4;
/**
* @author XIAO
* 2024/6/7
*/
class Singleton04 {
public static void main(String[] args) {
SingleTon instance1 = SingleTon.getInstance();
System.out.println("instance1 值 = " + instance1.getValue());
instance1.setValue(8);
SingleTon instance2 = SingleTon.getInstance();
System.out.println("instance2 值 = " + instance2.getValue());
System.out.println("instance1 hashCode = " + instance1.hashCode());
System.out.println("instance2 hashCode = " + instance2.hashCode());
}
}
class SingleTon {
int value = 1;
private static SingleTon instance;
//1. 私有化Singleton类防止New
private SingleTon(){}
//2. 提供一个静态公有方法.
//所有使用getInstance方法时都将同步等待
public static SingleTon getInstance(){
if(instance == null){
//使用synchronized同步锁住了创建类对象 线程不安全
synchronized(SingleTon.class){
instance = new SingleTon();
}
}
return instance;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
【注意】
此处虽然使用同步锁住了创建类对象的步骤,缩小了锁的范围(由方法转到行执行)。
本意是想提升效率,但是只锁住创建只会延缓创建过程(其他的线程依然通过了 if 的判断),所以这种方法连最基本的线程安全也做不到。
非常不推荐