单例模式

本文介绍了Java中的单例模式,包括饿汉式和懒汉式的实现,并探讨了线程安全问题。同时,展示了如何通过对象池来管理有限数量的对象,以提高程序效率。最后,给出了对象池的饿汉式和懒汉式实现,以及测试结果,说明了对象池如何在需要时返回或回收对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

介绍

  • 创建型模式
  • 有些对象只需创建少量且固定个数的即可,重复创建对象会导致程序运行效率降低。,因为创建对象是耗时操作。
  • 该模式根据创建对象时机的不同分为懒汉式饿汉式

运用

  • 单例模式的核心是:构造方法私有,向外部提供一个接口,用以获取单例对象。
private Demo(){}
  • 饿汉式:类加载时,直接创建对象
private static Demo demo = new Demo();

//获取实例的接口
public static Demo getInstance(){
	return demo;
}
  • 懒汉时,当外部调用接口时才创建对象
private static Demo demo;

public static Demo getInstance(){
	if(demo == null) demo = new Demo();
	return demo;
}
  • 以上的操作,将导致线程不安全。试想一下,当A线程刚判断完,demo为空将要创建对象时,B线程也进行了判断,判断也为空,该线程也会进行创建对象的操作。那么,最终的结果就是创建了多个对象,与初衷不符。
  • 解决方案:
private static volatile Demo demo;

public static synchronized Demo getInstance(){
	if(demo == null) demo = new Demo();
	return demo;
}
  • 单例模式不意味着只创建一个对象,而是固定个数的、有限的对象。
  • 对象池-饿汉式
import java.util.ArrayList;
import java.util.List;

public class Demo {

    private static int number = 3;//对象池大小

    private Demo(){}
    
    //对象池
    private static List<Demo> listOfDemo = new ArrayList<>();

    //对象池初始化
    static {
        for (int i = 1; i <= number; ++i) {
            listOfDemo.add(new Demo());//初始化对象池
        }
    }

    //获取实例的接口
    public static Demo getInstance() {
        if (listOfDemo.size() > 0) return listOfDemo.remove(listOfDemo.size() - 1);
        else return null;
    }

    public void close() {
        if (listOfDemo.size() == number) return;//以防通过该方法,增加对象引用个数
        listOfDemo.add(this);
    }

}
  • 测试代码及结果
public class User {
    public static void main(String[] args) {
    	//获取对象
        Demo demo1 = Demo.getInstance();
        Demo demo2 = Demo.getInstance();
        Demo demo3 = Demo.getInstance();
        Demo demo4 = Demo.getInstance();
		//打印对象,查看对象获取情况
        System.out.println(demo1);
        System.out.println(demo2);
        System.out.println(demo3);
        System.out.println(demo4);
		//返回对象池
        if (demo1 != null) demo1.close();
        System.out.println("demo1: " + demo1);

        Demo demo5 = Demo.getInstance();
        System.out.println(demo5);
    }
}

结果:
Demo@4f3f5b24
Demo@15aeb7ab
Demo@7b23ec81
null
demo1: Demo@4f3f5b24
Demo@4f3f5b24
  • 值得注意的是,在demo.close();执行之后,我并没有demo = null;,因为过期引用的销毁最好不要手动编写代码去实现,而是由其生命周期决定。
  • 对象池-懒汉式
import java.util.ArrayList;
import java.util.List;

public class Demo {

    private static int number = 3;//对象池大小

    private static int current = 0;//外部正在使用中的本类实例对象个数

    private Demo() {
    }

    //对象池
    private static List<Demo> listOfDemo = new ArrayList<>();

    //获取实例的接口
    public static Demo getInstance() {
    	//当对象池最大个数 > 当前对象池的对象个数+外部正使用中的对象个数
    	//意味着我们还可以继续创建对象
        if (number > listOfDemo.size() + current) {
            listOfDemo.add(new Demo());
        }
        //当外部正使用中的对象个数 < 对象池最大个数
        //意味着对象池中有空闲的对象可以使用
        if (current < number) {
            current++;
            return listOfDemo.remove(listOfDemo.size() - 1);
        }
        return null;
    }

    public void close() {
        if (listOfDemo.size() == number) return;//以防通过该方法,增加对象引用个数
        listOfDemo.add(this);
        current--;
    }

}

结果:
Demo@4f3f5b24
Demo@15aeb7ab
Demo@7b23ec81
null
demo1: Demo@4f3f5b24
Demo@4f3f5b24
  • java中的枚举就属于单例模式哦
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值