java中的四种单例实现方式

在java中,单例设计模式是非常常见的设计模式,对单例设计模式的概念,不做过多的介绍,下面将逐一介绍四种单例设计模式:

1、第一种单例设计模式

1.1 代码实现

package com.singleton.one;
/**
 * 第一种单例设计模式
 * @author Administrator
 *
 */
public class SingleTonOne {
	// 实例化
	private static SingleTonOne instance = new SingleTonOne();

	// 私有构造方法
	private SingleTonOne(){
		System.out.println("---singleton one---");
	}

	// 获取单例实例
	public static SingleTonOne getInstance(){
		return instance;
	}

	// 静态方法
	public static void hello(){
		System.out.println("---singleton one hello---");
	}

}

1.2 相关测试

package com.singleton.test;

import static org.junit.Assert.assertTrue;

import org.junit.Test;

import com.singleton.one.SingleTonOne;

public class TestSingleTonOne {

	/**
	 * 测试是否是单例
	 */
	@Test
	public void testSingleTonOne(){
		SingleTonOne one1 = SingleTonOne.getInstance();
		SingleTonOne one2 = SingleTonOne.getInstance();
		assertTrue(one1 == one2);
	}

	/**
	 * 测试第一种单例的加载方式
	 * 运行结果:
	 * ---singleton one---
	 * ---singleton one hello---
	 * 1、先执行了私有构造方法;
	 * 2、然后再执行静态方法
	 * 结论:
	 * 当单纯的调用静态方法时,调用了私有构造方式是没有必要,也就是
	 * 无法实现懒加载
	 */
	@Test
	public void testSingleTonOneLoad(){
		SingleTonOne.hello();
	}

}

2、第二种单例

2.1 代码实现

package com.singleton.one;
/**
 * 第二种单例设计模式
 * @author Administrator
 *
 */
public class SingleTonTwo {

	private static SingleTonTwo instance ;

	private SingleTonTwo(){
		System.out.println("-- singleton two --");
	}

	/**
	 * 懒加载处理,但是线程不安全
	 * @return
	 */
//	public static SingleTonTwo getInstance(){
//		if (instance == null){
//			instance = new SingleTonTwo();
//		}
//
//		return instance;
//	}
	/**
	 * 上述注释的getInstance是非线程安全的,该方法做了同步处理;
	 * 但是由于线程处理,往往效率不高
	 */
	public static synchronized SingleTonTwo getInstance(){
		if (instance == null){
			instance = new SingleTonTwo();
		}

		return instance;
	}

	public static void hello(){
		System.out.println("-- single ton two hello --");
	}

}

2.2 相关测试

package com.singleton.test;

import static org.junit.Assert.assertTrue;

import org.junit.Test;

import com.singleton.one.SingleTonTwo;

/**
 * 测试四种单例方式 -- 第二种单例(懒加载)
 * @author Administrator
 * 
 */
public class TestSingleTonTwo {

	/**
	 * 测试是否是单例
	 */
	@Test
	public void testSingleTonTwo(){
		SingleTonTwo one1 = SingleTonTwo.getInstance();
		SingleTonTwo one2 = SingleTonTwo.getInstance();
		assertTrue(one1 == one2);
	}

	/**
	 * 测试第二种单例测试
	 * 运行结果:
	 * -- single ton two hello --
	 * 结论:
	 * 运行静态方法时,不会调用私有构造方法(即:懒加载)
	 */
	@Test
	public void testSingleTonTwoLoad(){
		SingleTonTwo.hello();
	}
}

3、内部类实现单例

3.1 代码实现

package com.singleton.one;
/**
 * 内部类实现单例
 */
public class SingleTonThree {

	private SingleTonThree(){
		System.out.println("-- SingleTon Three --");
	}
	/**
	 * 内部类实例化
	 * @author Administrator
	 *
	 */
	private static class SingleTonThreeHandler{
		public static SingleTonThree instance = new SingleTonThree();
	}

	/**
	 * 通过内部类,获取实例
	 * @return
	 */
	public static SingleTonThree getInstance(){
		return SingleTonThreeHandler.instance;
	}

	public static void hello(){
		System.out.println("-- SingleTonThree hello --");
	}

}

3.2 相关测试

package com.singleton.test;

import static org.junit.Assert.assertTrue;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import org.junit.Test;

import com.singleton.one.SingleTonThree;

/**
 * 测试四种单例方式 -- 第三种单例(内部静态类)
 * @author Administrator
 * 
 */
public class TestSingleTonThree {

	/**
	 * 测试是否是单例
	 */
	@Test
	public void testSingleTonThree(){
		SingleTonThree one1 = SingleTonThree.getInstance();
		SingleTonThree one2 = SingleTonThree.getInstance();
		assertTrue(one1 == one2);
	}

	/**
	 * 第三种单例测试
	 * 运行结果:
	 * -- SingleTonThree hello --
	 * 结论:
	 * 没有触发构造方法,仅仅执行了方法内部逻辑;实现了懒加载方式。
	 */
	@Test
	public void testSingleTonThreeLoad(){
		SingleTonThree.hello();
	}
}

4、枚举实现单例

4.1 代码实现

package com.singleton.one;
/**
 * 枚举类型实现单例
 * @author Administrator
 *
 */
public enum SingleTonEnum {
	/**
	 * 单例实例
	 */
	INSTANCE;

	private SingleTonEnum(){
		System.out.println("-- enum singleton --");
	}

	public static void hello(){
		System.out.println("-- eum singleton hello --");
	}

}

4.2 相关测试

package com.singleton.test;

import org.junit.Test;
import static org.junit.Assert.*;
import com.singleton.one.SingleTonEnum;

/**
 * 测试枚举类型单例
 * @author Administrator
 *
 */
public class TestSingleTonEnum {

	/**
	 * 测试是否是单例
	 */
	@Test
	public void testSingleTonEnum(){
		SingleTonEnum enum1 = SingleTonEnum.INSTANCE;
		SingleTonEnum enum2 = SingleTonEnum.INSTANCE;
		assertTrue(enum1 == enum2);
	}
	/**
	 * 测试是否懒加载
	 * 结果:
	 * -- enum singleton --
	 * -- eum singleton hello --
	 * 该枚举类型,无法懒加载
	 */
	@Test
	public void testSingleTonEnum1(){
		SingleTonEnum.hello();
	}
}

5、四种单例效率测试

package com.singleton.test;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.singleton.one.SingleTonEnum;
import com.singleton.one.SingleTonOne;
import com.singleton.one.SingleTonThree;
import com.singleton.one.SingleTonTwo;

/**
 * 测试四种单例的效率
 * 运行结果:
 *  ---singleton one---
 *	3
 *	-- singleton two --
 *	57
 *	-- SingleTon Three --
 *  4
 *	-- enum singleton --
 *	3
 * 结果分析:
 * 第二种时间消耗最多,由于其同步处理了,而导致更多的开销
 * @author Administrator
 *
 */
public class TestSingleTon {

	long start;
	long end;

	@Before
	public void setUp(){
		start = System.currentTimeMillis();
	}

	@Test
	public void testSingleTonOne(){
		for (int i = 0; i < 1000000; i++){
			SingleTonOne instance = SingleTonOne.getInstance();
		}
	}

	@Test
	public void testSingleTonTwo(){
		for (int i = 0; i < 1000000; i++){
			SingleTonTwo instance = SingleTonTwo.getInstance();
		}
	}

	@Test
	public void testSingleTonThree(){
		for (int i = 0; i < 1000000; i++){
			SingleTonThree instance = SingleTonThree.getInstance();
		}
	}

	@Test
	public void testSingleTonEnum(){
		for (int i = 0; i < 1000000; i++){
			SingleTonEnum enum1 = SingleTonEnum.INSTANCE;
		}
	}

	@After
	public void tearDown(){
		end = System.currentTimeMillis();
		System.out.println(end - start);
	}

}

6、总结

第一种单例:不具备懒加载的功效;

第二种单例:懒加载、如果分为线程安全和非线程安全两种,当使用线程安全同步时,会影响效率。

第三种单例:懒加载、且适合多线程,效率很高;但是可以通过java反射来实例化多个实例,因此在一般情况下,该方式实现比较好;

第四种单例:必须在jdk5.0以上才具备的,未实现懒加载,多线程友好,并且无法通过java反射来实例化多个实例。

在一般情况下,建议使用第三种和第四种方式。

java中的四种单例实现方式

时间: 2024-10-04 20:01:21

java中的四种单例实现方式的相关文章

JAVA中的四种引用以及ReferenceQueue和WeakHashMap的使用示例

简介: 本文主要介绍JAVA中的四种引用: StrongReference(强引用).SoftReferenc(软引用).WeakReferenc(弱引用).PhantomReference(虚引用)的作用.同时我们还将介绍ReferenceQueue和WeakHashMap的功能和使用示例. 欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 1. JAVA中的四种引用 四种引用中,软引用.若引用.虚引用都需要相关类来创建.创建的时候

Java 中的四种引用

1.强引用(Strong Reference)在 Java 中四种引用中是"最强"的,我们平时通过 new 关键字创建的对象都属于强引用,如下面的代码: Person person = new Person();其中的 person 就是一个强引用,只有当它不再被使用后才会被垃圾回收器回收掉.当内存不足时,但是其依然在被使用中,那么垃圾回收器也不会回收其引用的对象:JVM 宁愿报"内存泄漏错误 (OutofMemoryError)",终止程序也不会回收此引用所关联的

Java 中的四种引用及垃圾回收策略

Java 中有四种引用:强引用.软引用.弱引用.虚引用: 其主要区别在于垃圾回收时是否进行回收: 1.强引用 使用最普遍的引用.如果一个对象具有强引用,那就 类似于必不可少的生活用品,垃圾回收器绝不会回收它.当内存空 间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题. 2.软引用(SoftReference) 如果一个对象只具有软引用,那就类似于可有可物的生活用品.如果内存空间足够,垃圾回收器就不会回收它,如果

java中的四种引用

Java 中有四种引用:强引用.软引用.弱引用.虚引用: 其主要区别在于垃圾回收时是否进行回收: 1.强引用 使用最普遍的引用.如果一个对象具有强引用,那就 类似于必不可少的生活用品,垃圾回收器绝不会回收它.当内存空 间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题. 2.软引用(SoftReference) 如果一个对象只具有软引用,那就类似于可有可物的生活用品.如果内存空间足够,垃圾回收器就不会回收它,如果

Java中的四种引用类型比较

1.引用的概念 引用这个概念是与JAVA虚拟机的垃圾回收有关的,不同的引用类型对应不同的垃圾回收策略或时机. 垃圾收集可能是大家感到难于理解的较难的概念之一,因为它并不能总是毫无遗漏地解决Java运行时环境中堆管理的问题. 垃圾回收的大致思路是:当Java虚拟机觉得内存不够用的时候,会触发垃圾回收操作(GC),清除无用的对象,释放内存.可是如何判断一个对象是否是垃圾呢?其中的一个方法是计算指向该对象的引用数量,如果引用数量为0,那么该对象就为垃圾(Thread对象是例外),否则还有用处,不能被回

Egret中的三种单例写法

1 普通的单例写法 class Single{ private static instance:Single; public static getInstance():Single{ if(this.instance == null){ this.instance = new Single(); } return this.instance; } public run(){ } } Single.getInstance().run(); 2 Module写法.仿照的Egret中Res资源类写法.

Java中的四种引用类型,强引用,软引用,弱引用,虚引用

对于Java中的垃圾回收机制来说,对象是否被回收的标准在于该对象是否被引用.因此,引用也是JVM进行内存管理的一个重要概念. Java中对象的引用一般有以下4种类型: 1强引用  2软引用  3弱引用  4虚引用 以下一一介绍其用法和区别 1强引用:在Java中最常见的就是强引用,把一个对象赋给一个引用变量,这个引用变量就是一个强引用.当一个对象被强引用变量引用时,它处于可达状态,它是不可能被垃圾回收机制回收的,即使该对象以后永远都不会被用到JVM也不会回收.因此强引用是造成Java内存泄漏的主

java中的四种监听类用法

在此列举四种方法: 自身类实现ActionListener接口,作为事件监听器 通过匿名类处理 通过内部类处理 通过外部类处理 下面依次介绍: 第一种:自身类实现ActionListener接口,作为事件监听器. 这种方法是最基本的,也是初学者经常使用的,我当初即是如此. import java.awt.Color; import java.awt.Container; import java.awt.FlowLayout; import java.awt.event.ActionEvent;

java中的四种内部类

java中的内部类分为四个: 成员内部类 静态内部类 局部内部类 匿名内部类 1. 成员内部类: 定义在另一个类(外部类)的内部,而且与成员方法和属性平级叫成员内部类,......相当于外部类的非静态方法,如果被static修饰,就变成静态内部类了. )成员内部类中不能存在static关键字,即,不能声明静态属性.静态方法.静态代码块等.[非静态内部类也可以定义静态成员但需要同时有final关键词修饰,静态方法鉴于无法用final修饰,仍必须是在静态内部类 或者非内部类中定义.] )创建成员内部