PS:首先我们要先知道什么是单例,为什么要用单例,用的好处是什么等问题来看。
1:java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍两种:懒汉式单例、饿汉式单例
单例模式有以下特点:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。
2:懒汉式
先把单例类写出来
public class SingletonTest { //懒汉式单例类.在第一次调用的时候实例化自己 private SingletonTest() {} private static SingletonTest single=null; //静态工厂方法 public static SingletonTest getInstance() { if (single == null) { single = new SingletonTest(); System.out.println("创建一次"); } return single; } public void show(){ System.out.println("我是show"); } }
这里直接上代码,代码中有详解
public class SingletonTest2 { public static void main(String[] args) { // TODO Auto-generated method stub //故意写获取两次,创建两个对象 SingletonTest singleton=SingletonTest.getInstance(); SingletonTest singleton2=SingletonTest.getInstance(); //Singleton对象只创建一次,但是写两次还是可以的,而且方法都是可以调用的,但是看下面 singleton.show(); singleton2.show(); //两个对象的表现形式一样 if(singleton == singleton2){ System.out.println("该对象的字符串表示形式:"); System.out.println("singleton :"+singleton.toString()); System.out.println("singleton2:"+singleton2.toString()); }
由上面的图可以看出就算多创建几个对象,在底部也是只有一个singleton对象实例,而且创建出来的对象的字符串表现形式也是一样的,有的人肯定有疑问,那平常两个对象是什么样子的呢,我下面给你解释说明,在这之前我写说一下这个懒汉式需要注意的地方,它是线程不安全的,并发环境下很可能出现多个Singleton实例,有很多方法可以解决,比如说同步锁,静态内部类等,这里主要说静态内部类,这个比较好点,
public class Singleton3 { private static class SingletonHolder { private static final Singleton3 INSTANCE = new Singleton3(); } private Singleton3 (){} public static final Singleton3 getInstance() { System.out.println("singleton创建"); return SingletonHolder.INSTANCE; } }
调用:
Singleton3 singleton3=Singleton3.getInstance(); Singleton3 singleton4=Singleton3.getInstance(); if(singleton3 == singleton4){ System.out.println("该对象的字符串表示形式:"); System.out.println("singleton3:"+singleton3.toString()); System.out.println("singleton4:"+singleton4.toString()); }
结果图:
这里我也是创建了两个对象来说明,神奇的是打印了两次singleton创建,这难道是又创建成功了的对象吗?答案是:虽然打印了两次,对象名也有两个,但是该对象的字符串表示形式还是一样的,而且大家都知道static的用法,就是在类被加载的同时该singleton对象就已经被创建,后期不会再被创建,就算后期自己又调用了getInstance()方法,但底层还是公用的一个Singleton对象.
同样,我写了一个普通的类,来同时创建两个对象,并且打印他们的toString()方法,如下:
QuBie qb1=new QuBie(); QuBie qb2=new QuBie(); if(qb1 == qb2){ System.out.println("该对象的字符串表示形式:"); System.out.println("singleton3:"+qb1.toString()); System.out.println("singleton4:"+qb2.toString()); }else{ System.out.println("该对象的字符串表示形式:"); System.out.println("singleton3:"+qb1.toString()); System.out.println("singleton4:"+qb2.toString()); }
由此可看出来对象的字符串表示形式是不一样的
3:饿汉式单例
饿汉式单例类.在类初始化时,已经自行实例化
public class Singleton1 { private Singleton1() {} private static final Singleton1 single = new Singleton1(); //静态工厂方法 public static Singleton1 getInstance() { return single; } }
因为这本身就是static修饰的方法,所以是在类加载的时候被创建,后期不会再改变,所以线程是安全的。
忍者必须死34399账号登录版 最新版v1.0.138v2.0.72
下载勇者秘境oppo版 安卓版v1.0.5
下载忍者必须死3一加版 最新版v1.0.138v2.0.72
下载绝世仙王官方正版 最新安卓版v1.0.49
下载Goat Simulator 3手机版 安卓版v1.0.8.2
Goat Simulator 3手机版是一个非常有趣的模拟游
Goat Simulator 3国际服 安卓版v1.0.8.2
Goat Simulator 3国际版是一个非常有趣的山羊模
烟花燃放模拟器中文版 2025最新版v1.0
烟花燃放模拟器是款仿真的烟花绽放模拟器类型单机小游戏,全方位
我的世界动漫世界 手机版v友y整合
我的世界动漫世界模组整合包是一款加入了动漫元素的素材整合包,
我的世界贝爷生存整合包 最新版v隔壁老王
我的世界MITE贝爷生存整合包是一款根据原版MC制作的魔改整