java写一个单例模式(如何写一个标准的Java单例模式)
本文目录
如何写一个标准的Java单例模式
java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。单例模式有一下特点:1、单例类只能有一个实例。2、单例类必须自己自己创建自己的唯一实例。3、单例类必须给所有其他对象提供这一实例。单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。首先看一个经典的单例实现。public class Singleton {private static Singleton uniqueInstance = null;private Singleton() {// Exists only to defeat instantiation.}public static Singleton getInstance() {if (uniqueInstance == null) {uniqueInstance = new Singleton();}return uniqueInstance;}// Other methods...}Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。(事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论,姑且掩耳盗铃地认为反射机制不存在。)但是以上实现没有考虑线程安全问题。所谓线程安全是指:如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。显然以上实现并不满足线程安全的要求,在并发环境下很可能出现多个Singleton实例。//////////////////////////////////////////////////////////////////////验证单例模式的示例//////////////////////////////////////////////////////////////////////public class TestStream {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}// 该类只能有一个实例private TestStream() {} // 私有无参构造方法// 该类必须自行创建// 有2种方式private static TestStream ts1 = null;// 这个类必须自动向整个系统提供这个实例对象public static TestStream getTest() {if (ts1 == null) {ts1 = new TestStream();}return ts1;}public void getInfo() {System.out.println(“output message “ + name);}public static void main(String args) {TestStream s = TestStream.getTest();s.setName(“张孝祥 1“);System.out.println(s.getName());TestStream s1 = TestStream.getTest();s1.setName(“张孝祥 2“);System.out.println(s1.getName());s.getInfo();s1.getInfo();if (s == s1) {System.out.println(“创建的是同一个实例“);} else if (s != s1) {System.out.println(“创建的不是同一个实例“);} else {System.out.println(“application error“);}}}////////////////////////////////////////////
如何用Java实现单例模式
单例模式:就是一个类仅创建一个对象;
public class Singleton { private static volatile Singleton singleton = null; private Singleton(){}// 构造方法 public static Singleton getSingleton(){// 单例模式 if(singleton == null){ synchronized (Singleton.class){ if(singleton == null){ singleton = new Singleton(); } } } return singleton; } }java中的单例模式的代码怎么写
我从我的博客里把我的文章粘贴过来吧,对于单例模式模式应该有比较清楚的解释:单例模式在我们日常的项目中十分常见,当我们在项目中需要一个这样的一个对象,这个对象在内存中只能有一个实例,这时我们就需要用到单例。一般说来,单例模式通常有以下几种:1.饥汉式单例public class Singleton { private Singleton(){}; private static Singleton instance = new Singleton(); public static Singleton getInstance(){ return instance; }}这是最简单的单例,这种单例最常见,也很可靠!它有个唯一的缺点就是无法完成延迟加载——即当系统还没有用到此单例时,单例就会被加载到内存中。在这里我们可以做个这样的测试:将上述代码修改为:public class Singleton { private Singleton(){ System.out.println(“createSingleton“); }; private static Singleton instance = new Singleton(); public static Singleton getInstance(){ return instance; } public static void testSingleton(){ System.out.println(“CreateString“); }}而我们在另外一个测试类中对它进行测试(本例所有测试都通过Junit进行测试)public class TestSingleton { @Test public void test(){ Singleton.testSingleton(); }}输出结果:createSingletonCreateString 我们可以注意到,在这个单例中,即使我们没有使用单例类,它还是被创建出来了,这当然是我们所不愿意看到的,所以也就有了以下一种单例。2.懒汉式单例public class Singleton1 { private Singleton1(){ System.out.println(“createSingleton“); } private static Singleton1 instance = null; public static synchronized Singleton1 getInstance(){ return instance==null?new Singleton1():instance; } public static void testSingleton(){ System.out.println(“CreateString“); }}上面的单例获取实例时,是需要加上同步的,如果不加上同步,在多线程的环境中,当线程1完成新建单例操作,而在完成赋值操作之前,线程2就可能判断instance为空,此时,线程2也将启动新建单例的操作,那么多个就出现了多个实例被新建,也就违反了我们使用单例模式的初衷了。我们在这里也通过一个测试类,对它进行测试,最后面输出是CreateString可以看出,在未使用到单例类时,单例类并不会加载到内存中,只有我们需要使用到他的时候,才会进行实例化。这种单例解决了单例的延迟加载,但是由于引入了同步的关键字,因此在多线程的环境下,所需的消耗的时间要远远大于第一种单例。我们可以通过一段测试代码来说明这个问题。public class TestSingleton { @Test public void test(){ long beginTime1 = System.currentTimeMillis(); for(int i=0;i《100000;i++){ Singleton.getInstance(); } System.out.println(“单例1花费时间:“+(System.currentTimeMillis()-beginTime1)); long beginTime2 = System.currentTimeMillis(); for(int i=0;i《100000;i++){ Singleton1.getInstance(); } System.out.println(“单例2花费时间:“+(System.currentTimeMillis()-beginTime2)); }}最后输出的是:单例1花费时间:0单例2花费时间:10 可以看到,使用第一种单例耗时0ms,第二种单例耗时10ms,性能上存在明显的差异。为了使用延迟加载的功能,而导致单例的性能上存在明显差异,是不是会得不偿失呢?是否可以找到一种更好的解决的办法呢?既可以解决延迟加载,又不至于性能损耗过多,所以,也就有了第三种单例:3.内部类托管单例public class Singleton2 { private Singleton2(){} private static class SingletonHolder{ private static Singleton2 instance=new Singleton2(); } private static Singleton2 getInstance(){ return SingletonHolder.instance; }}在这个单例中,我们通过静态内部类来托管单例,当这个单例被加载时,不会初始化单例类,只有当getInstance方法被调用的时候,才会去加载SingletonHolder,从而才会去初始化instance。并且,单例的加载是在内部类的加载的时候完成的,所以天生对线程友好,而且也不需要synchnoized关键字,可以说是兼具了以上的两个优点。4.总结一般来说,上述的单例已经基本可以保证在一个系统中只会存在一个实例了,但是,仍然可能会有其他的情况,导致系统生成多个单例,请看以下情况:public class Singleton3 implements Serializable{ private Singleton3(){} private static class SingletonHolder{ private static Singleton3 instance = new Singleton3(); } public static Singleton3 getInstance(){ return SingletonHolder.instance; }}通过一段代码来测试:@Test public void test() throws Exception{ Singleton3 s1 = null; Singleton3 s2 = Singleton3.getInstance(); //1.将实例串行话到文件 FileOutputStream fos = new FileOutputStream(“singleton.txt“); ObjectOutputStream oos =new ObjectOutputStream(fos); oos.writeObject(s2); oos.flush(); oos.close(); //2.从文件中读取出单例 FileInputStream fis = new FileInputStream(“singleton.txt“); ObjectInputStream ois = new ObjectInputStream(fis); s1 = (Singleton3) ois.readObject(); if(s1==s2){ System.out.println(“同一个实例“); }else{ System.out.println(“不是同一个实例“); } }输出:不是同一个实例 可以看到当我们把单例反序列化后,生成了多个不同的单例类,此时,我们必须在原来的代码中加入readResolve()函数,来阻止它生成新的单例public class Singleton3 implements Serializable{ private Singleton3(){} private static class SingletonHolder{ private static Singleton3 instance = new Singleton3(); } public static Singleton3 getInstance(){ return SingletonHolder.instance; } //阻止生成新的实例 public Object readResolve(){ return SingletonHolder.instance; }}再次测试时,就可以发现他们生成的是同一个实例了。
更多文章:

暴力破解软件(我的EXCEL忘记了密码,谁有暴力破解的软件,)
2025年3月13日 12:50

ppt制作幻灯片(PPT幻灯片怎么制作表格怎么设计图片怎么处理出想要的效果)
2025年2月22日 22:20

abap开发实例(SAP abap开发现在有一张内表ITAB里面有两个字段A和B数据如下:)
2025年3月11日 18:20

java swing包(java的Swing是轻量级组件,轻量级组件是什么意思)
2025年2月27日 09:20

sequence(identity 和sequence的区别)
2025年3月1日 02:50

access2007教程(数据库应用Access2007实例教程的内容简介)
2025年3月1日 16:50

outlined(transistor+outline是什么意思)
2025年2月12日 20:10

scrapped是什么意思(acceptable是什么意思)
2025年3月20日 21:50

reduce的名词形式(reduce relax ease区别)
2025年3月6日 02:10