当前位置: 首页 > 图灵资讯 > 技术篇> java设计模式之(单例模式)

java设计模式之(单例模式)

来源:图灵教育
时间:2023-06-11 09:16:17

单例模式(懒汉和饿汉)

Java中指的是单例设计模式 他是软件开发中最常用的设计模式之一。

单:唯一

例:实例

单例设计模式: 在整个系统中,只有一个实例对象可以获得和使用的代码模式

要点:

1.某一类只能有一个例子

构造器私有

2.它必须自己创建这个例子

它含有这种静态变量来保存这个唯一的例子

3.它必须向整个系统提供这个例子

1.直接暴露 2.采用静态变量get法获取

常见的单例形式

饿汉式: (直接创建对象 没有线程安全问题) 1.饿汉式直接实例化 (简单直观)

/**

* 饿汉式:

* 实例对象在类初始化时直接创建 无论你是否需要这个对象,你都会创建它

*

*/

public class Singleton {

public static final Singleton INSTANCE=new Singleton();

private Singleton1()

}

2.枚举式 (最简洁)

/**

* 饿汉式 枚举类型:表示该类型的对象有限

* 我们可以限制一个,成为单例

*/

public enum Singleton2 {

INSTANCE

}

3.饿汉式静态代码块 (适用于复杂实例化)

/**

* 饿汉式 静态代码块 方式

* 适用于 比较复杂 需要一堆初始化数据来创建对象

*/

public class Singleton {

public static final Singleton INSTANCE;

static {

INSTANCE = new Singleton3();

}

private Singleton3() {

}

}

创建实例:

public class Test {

public static void main(String[] args) {

Singleton s = Singleton.INSTANCE;

Singleton2 s2 = Singleton2.INSTANCE;

Singleton s3 = Singleton.INSTANCE;

System.out.println(s);

System.out.println(s2);

System.out.println(s3);

}

}

为什么饿汉风格没有线程安全问题?

因为:

按需加载,只加载一次。因此,当上述单个例类被加载时,将实例化一个对象并交给自己的引用,供系统使用。换句话说,在线程访问单例对象之前就已经创建了。此外,由于一个类只会在整个生命周期中加载一次,单个类只会创建一个例子,也就是说,每次线程只能得到唯一的对象。因此,饿汉单例自然是线程安全的。

懒汉式: (必要时创建对象(延迟创建对象) 存在线程安全问题) 1.线程不安全 (适用于单线程)

/**

* 懒汉式 延迟创建对象

* 使用私有结构器

* 用静态变量保存这个唯一的例子

* 提供静态方法 获得这个例子

*/

public class Singleton4 {

private static Singleton4 instance = null;

private Singleton4()

public static Singleton4 getInstance(){

if(instance==null){

instance = new Singleton4();

}

return instance;

}

}

2.线程安全 (适用于多线程)

/**

* 第一种

* 懒汉式 延迟创建对象 (线程安全)

*/

public class Singleton5 {

private static Singleton5 instance = null;

private Singleton5()

//在方法上加锁(synchronized) 确保线程安全 这种效率在高并发的情况下相对较低

public synchronized static Singleton5 getInstance(){

if(instance==null){

instance = new Singleton5();

}

return instance;

}

}

/**

* 第二种 DoubleCheck

* 懒汉式 延迟创建对象

*/

public class Singleton6 {

//加上volatile 保证jvm 代码不会重新排序

private static volatile Singleton6 instance = null;

private Singleton6()

//确保线程安全 doublecheck

public static Singleton6 getInstance(){

如果///在线程运行中 instance本身不同于空 那样,就没有必要继续进入锁 (效率高于直接锁定给方法)

if(instance==null){

synchronized (Singleton6.class){

if(instance==null){

instance = new Singleton6();

}

}

}

return instance;

}

}

3.静态内部类形式 (适用于多线程)

/**

* 当内部类被加载和初始文字时, 创建INSTANCE实例对象

* 静态内部类不会随着外部类的加载和初始化而自动初始化。它需要单独加载和初始化

* 因为它是在内部加载和初始单词中创建的 所以线程是安全的

*/

public class Singleton7 {

private Singleton7()

private static class inner{

private static final Singleton7 INSTANCE=new Singleton7();

}

public static Singleton7 getInstance(){

return inner.INSTANCE;

}

}