1.单例模式

单例模式

  • 定义:程序运行时,在java虚拟机中只存在该类的一个实例对象。
  • demo:
package mode;
public class SingleDemo {
// 创建SingleDemo单例对象
private static SingleDemo instance = new SingleDemo();
// 将构造方法设成私有的,这样该类就不会被实例化
private SingleDemo() {}
public static SingleDemo getInstance() {
return instance;
}
public void showMessage() {
System.out.println("这里是重要的信息");
}
}
class SingleAply{
public static void main(String[] args) {
SingleDemo singleDemo = SingleDemo.getInstance();
singleDemo.showMessage();
}
}

实现方式

懒汉式-线程不安全

懒汉式_线程不安全
优点 1.起到了延迟加载的效果
缺点 1.只能在单线程下使用
2.如果在多线程下,一个线程进入了if(single==null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这是便会产生多个实例。所以多线程不可以使用
结论 在实际开发中,不要使用这种方式
public class LazyNotSafe {
private static LazyNotSafe instance;
private LazyNotSafe() {}
public LazyNotSafe getInstance() {
if (instance == null) {
instance = new LazyNotSafe();
}
return instance;
}
}

懒汉式-线程安全

懒汉式_线程安全
优点 1.解决了线程不安全问题
缺点 1.效率太低,每个线程在想获得类的实例的时候,执行getInstance()方法都要进行同步。
2.而其实这个方法只执行一次实例化代码就够了,后面的想获得该类实例,直接return就行了。方法进行同步效率太低。
结论 在实际开发中,不要使用这种方式
public class LazySafe {
private static LazySafe instance;
private LazySafe() {}
public static synchronized LazySafe getInstance() {
if (instance == null) {
instance = new LazySafe();
}
return instance;
}
}

懒汉式-线程不安全同步代码块

懒汉式_同步代码块
优点 延迟加载
缺点 1.本意是对线程安全的懒汉式进行改进,因为其同步方法效率太低,改为同步产生的实例化代码块
2.线程不能同步。假如一个线程进入了if(instance==null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例
注意:synchronized同步代码块中,当释放锁后,会继续向下执行
结论 在实际开发中,不能用这种方式
public class LazyNoSafePiece {
private static LazyNoSafePiece instance;
private LazyNoSafePiece() {}
public LazyNoSafePiece getInstance() {
if (instance == null) {
synchronized(LazyNoSafePiece.class) {
instance = new LazyNoSafePiece();
}
}
return instance;
}
}

饿汉式-静态变量/静态代码块

饿汉式_静态变量/静态代码块
优点 在类加载的时候完成了实例化,避免了线程同步问题。
缺点 在类装载的时候就完成实例化,没有达到延迟加载的效果。如果从头到尾未使用过这个实例,则会造成内存的浪费
结论 这种单例模式可以使用,但可能会造成内存的浪费
class HungrySafe {
private static HungrySafe instance = new HungrySafe();
private HungrySafe() {}
public static HungrySafe getInstance() {
return instance;
}
}

class HungrySafe2 {
private static HungrySafe2 instance;
private HungrySafe2() {}
static {
instance = new HungrySafe2();
}
public static HungrySafe2 getInstance() {
return instance;
}
}

双重检查(推荐使用)

双重检查
优点 1.线程安全
2.延迟加载
3.效率较高
4.实例化代码只用执行一次,后面再次访问时,判断第一层if(xxx==null),直接return实例化对象,也避免的反复进行方法同步。
结论 在实际开发中,推荐使用
public class DoubleCheck {
private DoubleCheck doubleCheck;
private DoubleCheck() {}
public DoubleCheck getInstance() {
if (doubleCheck == null) {
synchronized(DoubleCheck.class) {
if (doubleCheck == null) {
doubleCheck = new DoubleCheck();
}
}
}
return doubleCheck;
}
}

静态内部类(推荐使用)

优势
如何保证实例时只有一个线程?
即如何保证线程安全?
类的静态属性只会在第一次加载类的时候初始化,在类进行初始化时,别的线程是无法进入的,所以线程安全
如何实现延迟加载 利用静态内部类,不是在xxx类被装载时立即实例化,而是在调用getInstance方法时,才会装载xxx类,从而完成xxx类的实例化
public class InnerClass {
// volatile:一有修改就更新到主存中去
private static volatile InnerClass instance;
private InnerClass() {}
private static class InnerInstance {
private final static InnerClass instance = new InnerClass();
}
public static InnerClass getInstance() {
return InnerInstance.instance;
}
}

枚举

枚举
优点 1.能避免多线程同步问题
2.自动支持序列化机制,防止反序列化重新创建新的对象,防止多次实例化。
注意1:枚举类的内部定义的枚举值就是该类的实例(且必须在第一行定义,当类初始化时,这些枚举值会被实例化)。
线程安全由于JVM保证,因为ClassLoader进行类加载时,加了同步锁synchronized。
注意2:枚举类型在序列化的时候Java仅仅是将枚举对象的name属性输出到结果中,反序列化的时候则是通过java.lang.Enum的valueOf方法来根据名字查找枚举对象,而不是通过调用 readObject()方法来返回一个新创建出来的对象。同时,编译器是不允许任何对这种序列化机制的定制的,因此禁用了writeObject、readObject、readObjectNoData、writeReplace和readResolve等方法。
enum EnumSingleton {
INSTANCE;
public void sayOK() {
System.out.println("ok");
}
}
class A {
public static void main(String[] args) {
System.out.println(EnumSingleton.INSTANCE);
EnumSingleton.INSTANCE.sayOK();
}
}
posted @   jsqup  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
历史上的今天:
2022-08-15 11. azkaban将调度结果发送到邮箱
2022-08-15 12. scala配置与创建
点击右上角即可分享
微信分享提示