23种设计模式----单例模式----创建型模式

版权声明:本文为博主原创文章,转载请注明作者。 https://blog.csdn.net/a18792721831/article/details/83312731

1.单例模式

单例模式主要是保证只有一个实例对象。

2.单例模式实现方式

1.饿汉式–静态常量
2.饿汉式–静态代码块
3.懒汉式–常见
4.懒汉式–同步方法
5.懒汉式–同步代码块
6.双重检查
7.静态内部类
8.枚举

3.构思对比项目

3.1对比方式

使用多线程的方式,同步访问单例模式的实例对象

3.2单例基类设计

import java.util.ArrayList;
import java.util.List;

public abstract class Singleton {
	
	private boolean isShow = false;
	
	public abstract void showName();
	
	private List<String> list = new ArrayList<String>();
	
	protected void add(String string){
		list.add(string);
	}
	
	protected void show(){
		
		for(int i = 0;i < list.size();i++){
			if(isShow)
				System.out.println(list.get(i));
		}
		System.out.println("总计:\t"+list.size());
		System.out.println();
		Runtime rt = Runtime.getRuntime();
		showName();
		System.out.println("当前可用内存:\t"+rt.freeMemory());
		System.out.println("结束:\t"+System.currentTimeMillis());
	}
}

说明:采用模板方法的设计模式,由基类规定方法的调用,以及要求子类必须实现的方法。
其中:为单例类抽取属性:isShow=====是否显示输出list中的每一项
list是多线程操作的对象,每一个线程对单例类的操作是添加到list中一个字符串
showName()是一个抽象方法,是基类要求子类必须实现的方法,这个方法输出了正在运行的单例对象所属的实现方式。
show方法输出此时系统的一些状态属性。

3.3线程基类

public abstract class Test implements Runnable {

	protected Integer index;

	public Test(Integer integer) {
		this.index = integer;
	}

	@Override
	public abstract void run();

}

说明:线程基类使用的是实现Runnable接口实现多线程。

3.4测试类基类设计

/**
 * 单例模式可以说是设计模式中最简单的一个设计模式 单例模式需要做的事情就是保证全局的实例对象是唯一的 因此,本次学习将尝试使用多线程并发来测试单例模式
 */
public abstract class Main {
	
	protected Integer sum = 1000;

	public void doTest(Class<?> test) {
		setThread();
		try {
			Thread.sleep(500);
		} catch (Exception e) {
			e.getMessage();
		}
		output();
	}

	public abstract void setThread();

	public abstract void output();

}

说明:测试基类有一个sum属性,这个属性控制对每一个单例实例对象进行访问的次数了,当sum=100表示将有100个线程对每一种实现的单例类的实例对象进行访问。
doTest()方法用来等待创建线程完成,或者定义如何创建线程和如何输出系统信息。
setThread方法表示测试子类必须实现对相应的线程进行自己的设置
output方法表示测试子类必须实现输出系统状态的方法。

4单例模式具体实现

4.1静态常量–饿汉式

/**
 * 第一种:静态常量--饿汉式
 * 分析:因为Singleton1的唯一实例在类被加载时就进行创建,
 * 所以可以很好的解决线程安全的问题
 * 缺点:有一定的可能性造成内存浪费,特别是如果单例对象中,
 * 保存有较大数据或者对象,但是在整个生命周期都没有被使用,
 * 那么会造成内存浪费。
 *
 */
public class Singleton1 extends Singleton{
	
	private final String NAME = "第一种:静态常量--饿汉式";
	
	private final static Singleton1 INSTANCE = new Singleton1();
	
	private Singleton1(){
		
	}
	
	public static Singleton1 getInstance(){
		return INSTANCE;
	}

	@Override
	public void showName() {
		System.out.println(NAME);
	}

}

4.2饿汉式,静态代码块

/**
 * 2.饿汉式,静态代码块 与第一种完全相同,只是写法不同
 */

public class Singleton2 extends Singleton {

	private final String NAME = "2.饿汉式,静态代码块";

	private static Singleton2 INSTANCE;

	static {
		INSTANCE = new Singleton2();
	}

	private Singleton2() {

	}

	public static Singleton2 getInstance() {
		return INSTANCE;
	}

	@Override
	public void showName() {
		System.out.println(NAME);
	}


}

4.3懒汉式–常规

package cn.com.startimes.Singleton;
/**
 * 3.懒汉式--常规
 * 节省内存,懒创建,使用时创建
 * 缺点:线程不安全,只能在单线程下使用。
 */

public class Singleton3 extends Singleton{

	private final String NAME = "3.懒汉式--常规";
	
	private static Singleton3 INSTANCE;
	
	private Singleton3(){
		
	}
	
	public static Singleton3 getInstance(){
		
		if(INSTANCE == null){
			INSTANCE = new Singleton3();
		}
		
		
		return INSTANCE;
	}

	@Override
	public void showName() {
		System.out.println(NAME);
	}

}

4.4懒汉式,同步方法

/**
 * 
 * 4.懒汉式,同步方法
 *
 */
public class Singleton4 extends Singleton {

	private final String NAME = "4.懒汉式,同步方法";

	private static Singleton4 INSTANCE;

	private Singleton4() {

	}

	public static synchronized Singleton4 getInstance() {
		if (INSTANCE == null) {
			INSTANCE = new Singleton4();
		}
		return INSTANCE;
	}

	@Override
	public void showName() {
		System.out.println(NAME);
	}


}

4.5懒汉式–同步代码块

/**
 * 5.懒汉式--同步代码块
 * 
 *
 */
public class Singleton5 extends Singleton {

	private final String NAME = "5.懒汉式--同步代码块";

	private static Singleton5 INSTANCE;

	private Singleton5() {

	}

	public static Singleton5 getInstance() {
		if (INSTANCE == null) {
			synchronized (Singleton5.class) {
				INSTANCE = new Singleton5();
			}
		}
		return INSTANCE;
	}

	@Override
	public void showName() {
		System.out.println(NAME);
	}



}

4.6双重检查

/**
 * 6.双重检查
 * 
 *
 */
public class Singleton6 extends Singleton{

	private final String NAME = "6.双重检查";
	
	private static volatile Singleton6 INSTANCE;
	
	private Singleton6(){
		
	}
	
	public static Singleton6 getInstance(){
		if(INSTANCE == null){
			synchronized(Singleton6.class){
				if(INSTANCE == null){
					INSTANCE = new Singleton6();
				}
			}
		}
		return INSTANCE;
	}

	@Override
	public void showName() {
		System.out.println(NAME);
	}

}

4.7静态内部类

/**
 * 7.静态内部类
 * 
 *
 */
public class Singleton7 extends Singleton {

	private final String NAME = "7.静态内部类";

	private Singleton7() {

	}

	private static class Inner {
		private static final Singleton7 INSTANCE = new Singleton7();
	}

	public static Singleton7 getInstance() {
		return Inner.INSTANCE;
	}

	@Override
	public void showName() {
		System.out.println(NAME);
	}

}

4.8枚举

package cn.com.startimes.Singleton;

import java.util.ArrayList;
import java.util.List;

/**
 * 8.枚举
 * 
 *
 */
public enum Singleton8{
	INSTANCE;
	
	private boolean isShow = false;
	
	private final String NAME = "8.枚举";
	
	public static Singleton8 getInstance(){
		return INSTANCE;
	}
	
	private List<String> list = new ArrayList<String>();
	
	public void add(String string){
		list.add(string);
	}
	
	public void show(){
		for(int i = 0;i < list.size();i++){
			if(isShow)
				System.out.println(list.get(i));
		}
		System.out.println("总计:\t"+list.size());
		System.out.println();
		Runtime rt = Runtime.getRuntime();
		showName();
		System.out.println("当前可用内存:\t"+rt.freeMemory());
		System.out.println("结束:\t"+System.currentTimeMillis());
	}
	
	public void showName(){
		System.out.println(NAME);
	}
	
}

5.线程类具体实现

5.1—4.1

import java.text.SimpleDateFormat;
import java.util.Date;

public class Test1 extends Test{

	public Test1(Integer integer) {
		super(integer);
	}

	@Override
	public void run() {
		Singleton1.getInstance().add(
				new SimpleDateFormat("HH:mm:ss,sss\t\t\t").format(new Date())
						.toString() + super.index);
	}

}

5.2–4.2

import java.text.SimpleDateFormat;
import java.util.Date;

public class Test2 extends Test{

	public Test2(Integer integer) {
		super(integer);
	}

	@Override
	public void run() {
		Singleton2.getInstance().add(
				new SimpleDateFormat("HH:mm:ss,sss\t\t\t").format(new Date())
						.toString() + super.index);
	}

}

5.3-4.3

import java.text.SimpleDateFormat;
import java.util.Date;

public class Test3 extends Test{

	public Test3(Integer integer) {
		super(integer);
	}

	@Override
	public void run() {
		Singleton3.getInstance().add(
				new SimpleDateFormat("HH:mm:ss,sss\t\t\t").format(new Date())
						.toString() + super.index);
	}

}

5.4–4.4

import java.text.SimpleDateFormat;
import java.util.Date;

public class Test4 extends Test{

	public Test4(Integer integer) {
		super(integer);
	}

	@Override
	public void run() {
		Singleton4.getInstance().add(
				new SimpleDateFormat("HH:mm:ss,sss\t\t\t").format(new Date())
						.toString() + super.index);
	}

}

5.5–4.5

import java.text.SimpleDateFormat;
import java.util.Date;

public class Test5 extends Test{

	public Test5(Integer integer) {
		super(integer);
	}

	@Override
	public void run() {
		Singleton5.getInstance().add(
				new SimpleDateFormat("HH:mm:ss,sss\t\t\t").format(new Date())
						.toString() + super.index);
	}

}

5.6–4.6

import java.text.SimpleDateFormat;
import java.util.Date;

public class Test6 extends Test{

	public Test6(Integer integer) {
		super(integer);
	}

	@Override
	public void run() {
		Singleton6.getInstance().add(
				new SimpleDateFormat("HH:mm:ss,sss\t\t\t").format(new Date())
						.toString() + super.index);
	}

}

5.7–4.7

import java.text.SimpleDateFormat;
import java.util.Date;

public class Test7 extends Test{

	public Test7(Integer integer) {
		super(integer);
	}

	@Override
	public void run() {
		Singleton7.getInstance().add(
				new SimpleDateFormat("HH:mm:ss,sss\t\t\t").format(new Date())
						.toString() + super.index);
	}

}

5.8–4.8

import java.text.SimpleDateFormat;
import java.util.Date;

public class Test8 extends Test{

	public Test8(Integer integer) {
		super(integer);
	}

	@Override
	public void run() {
		Singleton8.getInstance().add(
				new SimpleDateFormat("HH:mm:ss,sss\t\t\t").format(new Date())
						.toString() + super.index);
	}

}

6测试类具体实现

6.1–4.1–5.1

public class Main1 extends Main {

	public static void main(String[] args) {
		Main1 obj = new Main1();
		obj.doTest(Test1.class);
	}

	@Override
	public void setThread() {
		for (int i = 0; i < sum; i++) {
			new Thread(new Test1(i), i + "").start();
		}
	}

	@Override
	public void output() {
		Singleton1.getInstance().show();
	}

}

6.2–4.2–5.2

public class Main2 extends Main {

	public static void main(String[] args) {
		Main2 obj = new Main2();
		obj.doTest(Test2.class);
	}

	@Override
	public void setThread() {
		for (int i = 0; i < sum; i++) {
			new Thread(new Test2(i), i + "").start();
		}
	}

	@Override
	public void output() {
		Singleton2.getInstance().show();
	}

}

6.3–4.3–5.3

/**
 * 线程不安全,因为存在可能创建多个实例, 那么后面的实例会覆盖掉之前的实例,造成数据丢失
 *
 */
public class Main3 extends Main {

	public static void main(String[] args) {
		Main3 obj = new Main3();
		obj.doTest(Test3.class);
	}

	@Override
	public void setThread() {
		for (int i = 0; i < sum; i++) {
			new Thread(new Test3(i), i + "").start();
		}
	}

	@Override
	public void output() {
		Singleton3.getInstance().show();
	}

}

6.4–4.4–5.4

public class Main4 extends Main{

	public static void main(String[] args) {
		Main4 obj = new Main4();
		obj.doTest(Test4.class);
	}

	@Override
	public void setThread() {
		for(int i = 0; i < sum;i++){
			new Thread(new Test4(i),i+"").start();
		}
	}

	@Override
	public void output() {
		Singleton4.getInstance().show();
		}

}

6.5–4.5–5.5

public class Main5 extends Main {

	public static void main(String[] args) {
		Main5 obj = new Main5();
		obj.doTest(Test5.class);
	}

	@Override
	public void setThread() {
		for (int i = 0; i < sum; i++) {
			new Thread(new Test5(i), i + "").start();
		}
	}

	@Override
	public void output() {
		Singleton5.getInstance().show();
	}

}

6.6–4.6–5.6

public class Main6 extends Main{

	public static void main(String[] args) {
		Main6 obj = new Main6();
		obj.doTest(Test6.class);
	}

	@Override
	public void setThread() {
		for (int i = 0; i < sum; i++) {
			new Thread(new Test6(i), i + "").start();
		}
	}

	@Override
	public void output() {
		Singleton6.getInstance().show();
		}

}

6.7–4.7–5.7

public class Main7 extends Main {

	public static void main(String[] args) {
		Main7 obj = new Main7();
		obj.doTest(Test7.class);
	}

	@Override
	public void setThread() {
		for (int i = 0; i < sum; i++) {
			new Thread(new Test7(i), i + "").start();
		}
	}

	@Override
	public void output() {
		Singleton7.getInstance().show();
	}

}

6.8–4.8–5.8

public class Main8 extends Main {

	public static void main(String[] args) {
		Main8 obj = new Main8();
		obj.doTest(Test8.class);
	}

	@Override
	public void setThread() {
		for (int i = 0; i < sum; i++) {
			new Thread(new Test8(i), i + "").start();
		}
	}

	@Override
	public void output() {
		Singleton8.getInstance().show();
	}

}

7项目主方法

public class RealMain {

	public static void startTime(){
		System.out.println("开始:\t"+System.currentTimeMillis());
	}
	
	public static void endTime(){
		System.out.println("结束:\t"+System.currentTimeMillis());
	}
	
	public static void startMemory(){
		Runtime rt = Runtime.getRuntime();
		System.out.println("当前可用内存"+rt.freeMemory());
		System.out.println("消耗的内存"+(rt.totalMemory() - rt.freeMemory()));
	}
	
	
	public static void sleep(Long time){
		System.out.println("线程睡眠"+time+"毫秒");
		try {
			Thread.sleep(time);
		} catch (Exception e) {
		}
	}
	
	public static void main(String[] args) {
		
		Runtime rt = Runtime.getRuntime();
		System.out.println("初始总内存"+rt.totalMemory());
		startMemory();
		startTime();
		Main1 main1 = new Main1();
		main1.doTest(Test1.class);
		
		sleep(1000L);
		System.out.println();
		
		startTime();
		startMemory();
		Main2 main2 = new Main2();
		main2.doTest(Test2.class);
		
		sleep(1000L);
		System.out.println();
		
		startTime();
		startMemory();
		Main3 main3 = new Main3();
		main3.doTest(Test3.class);
		
		sleep(1000L);
		System.out.println();
		
		startTime();
		startMemory();
		Main4 main4 = new Main4();
		main4.doTest(Test4.class);
		
		sleep(1000L);
		System.out.println();
		
		startTime();
		startMemory();
		Main5 main5 = new Main5();
		main5.doTest(Test5.class);
		
		sleep(1000L);
		System.out.println();
		
		startTime();
		startMemory();
		Main6 main6 = new Main6();
		main6.doTest(Test6.class);
		
		sleep(1000L);
		System.out.println();
		
		startTime();
		startMemory();
		Main7 main7 = new Main7();
		main7.doTest(Test7.class);
		
		sleep(1000L);
		System.out.println();
		
		startTime();
		startMemory();
		Main8 main8 = new Main8();
		main8.doTest(Test8.class);
		
	}

}

8.测试结果

8.1----sum=10

初始总内存16252928
当前可用内存15965096
消耗的内存287832
开始:	1540293390768
总计:	8

第一种:静态常量--饿汉式
当前可用内存:	14969464
结束:	1540293391311
线程睡眠1000毫秒

开始:	1540293392311
当前可用内存14969464
消耗的内存1283464
总计:	8

2.饿汉式,静态代码块
当前可用内存:	14063888
结束:	1540293392917
线程睡眠1000毫秒

开始:	1540293393917
当前可用内存14063888
消耗的内存2189040
总计:	8

3.懒汉式--常规
当前可用内存:	13067696
结束:	1540293394420
线程睡眠1000毫秒

开始:	1540293395420
当前可用内存13067696
消耗的内存3185232
总计:	8

4.懒汉式,同步方法
当前可用内存:	12162232
结束:	1540293395943
线程睡眠1000毫秒

开始:	1540293396944
当前可用内存12162232
消耗的内存4090696
总计:	6

5.懒汉式--同步代码块
当前可用内存:	15195944
结束:	1540293397468
线程睡眠1000毫秒

开始:	1540293398468
当前可用内存15195944
消耗的内存1056984
总计:	8

6.双重检查
当前可用内存:	14968912
结束:	1540293398970
线程睡眠1000毫秒

开始:	1540293399970
当前可用内存14968912
消耗的内存1284016
总计:	8

7.静态内部类
当前可用内存:	14741768
结束:	1540293400481
线程睡眠1000毫秒

开始:	1540293401482
当前可用内存14741768
消耗的内存1511160
总计:	9

8.枚举
当前可用内存:	14465488
结束:	1540293402022

方式 静态常量 静态代码块 常见 同步方法 同步代码块 双重检查 静态内部类 枚举
开始 1540293390768 1540293392311 1540293393917 1540293395420 1540293396944 1540293398468 1540293399970 1540293401482
结束 1540293391311 1540293392917 1540293394420 1540293395943 1540293397468 1540293398970 1540293400481 1540293402022
剩余内存 14969464 14063888 13067696 12162232 15195944 14968912 14741768 14465488
消耗内存 287832 1283464 2189040 3185232 4090696 1056984 1284016 1511160
list.size 8 8 8 8 6 8 8 9

8.2----sum=100

初始总内存16252928
当前可用内存15965096
消耗的内存287832
开始:	1540294269587
总计:	100

第一种:静态常量--饿汉式
当前可用内存:	12592952
结束:	1540294270144
线程睡眠1000毫秒

开始:	1540294271145
当前可用内存12592952
消耗的内存3659976
总计:	98

2.饿汉式,静态代码块
当前可用内存:	12370176
结束:	1540294271683
线程睡眠1000毫秒

开始:	1540294272683
当前可用内存12321224
消耗的内存3931704
总计:	95

3.懒汉式--常规
当前可用内存:	12098560
结束:	1540294273189
线程睡眠1000毫秒

开始:	1540294274189
当前可用内存12098560
消耗的内存4154368
总计:	97

4.懒汉式,同步方法
当前可用内存:	11826880
结束:	1540294274718
线程睡眠1000毫秒

开始:	1540294275719
当前可用内存11826880
消耗的内存4426048
总计:	91

5.懒汉式--同步代码块
当前可用内存:	11555296
结束:	1540294276232
线程睡眠1000毫秒

开始:	1540294277232
当前可用内存11555296
消耗的内存4697632
总计:	98

6.双重检查
当前可用内存:	15639728
结束:	1540294277767
线程睡眠1000毫秒

开始:	1540294278767
当前可用内存15639728
消耗的内存613200
总计:	97

7.静态内部类
当前可用内存:	15304528
结束:	1540294279273
线程睡眠1000毫秒

开始:	1540294280273
当前可用内存15304528
消耗的内存948400
Exception in thread "39" java.lang.ArrayIndexOutOfBoundsException: 58
	at java.util.ArrayList.add(ArrayList.java:352)
	at cn.com.startimes.Singleton.Singleton8.add(Singleton8.java:25)
	at cn.com.startimes.Singleton.Test8.run(Test8.java:14)
	at java.lang.Thread.run(Thread.java:662)
总计:	97

8.枚举
当前可用内存:	15000976
结束:	1540294280812

方式 静态常量 静态代码块 常见 同步方法 同步代码块 双重检查 静态内部类 枚举
开始 1540294269587 1540294271145 1540294272683 1540294274189 1540294275719 1540294277232 1540294278767 1540294280273
结束 1540294270144 1540294271683 1540294273189 1540294274718 1540294276232 1540294277767 1540294279273 1540294280812
剩余内存 12592952 12370176 12098560 11826880 11555296 15639728 15304528 15000976
消耗内存 287832 3659976 3931704 4154368 4426048 4697632 613200 948400
list.size 100 98 95 97 91 98 97 97

8.3----sum=1000

初始总内存16252928
当前可用内存15965096
消耗的内存287832
开始:	1540294686378
总计:	1000

第一种:静态常量--饿汉式
当前可用内存:	14595808
结束:	1540294686966
线程睡眠1000毫秒

开始:	1540294687966
当前可用内存14595808
消耗的内存1657120
总计:	999

2.饿汉式,静态代码块
当前可用内存:	12025192
结束:	1540294688518
线程睡眠1000毫秒

开始:	1540294689518
当前可用内存12025192
消耗的内存4227736
总计:	999

3.懒汉式--常规
当前可用内存:	13581920
结束:	1540294690063
线程睡眠1000毫秒

开始:	1540294691063
当前可用内存13581920
消耗的内存2671008
总计:	1000

4.懒汉式,同步方法
当前可用内存:	14779736
结束:	1540294691606
线程睡眠1000毫秒

开始:	1540294692607
当前可用内存14779736
消耗的内存1473192
总计:	990

5.懒汉式--同步代码块
当前可用内存:	14833528
结束:	1540294693150
线程睡眠1000毫秒

开始:	1540294694150
当前可用内存14833528
消耗的内存1419400
总计:	1000

6.双重检查
当前可用内存:	12631504
结束:	1540294694696
线程睡眠1000毫秒

开始:	1540294695696
当前可用内存12631504
消耗的内存3621424
总计:	1000

7.静态内部类
当前可用内存:	11329760
结束:	1540294696242
线程睡眠1000毫秒

开始:	1540294697242
当前可用内存11329760
消耗的内存4923168
总计:	998

8.枚举
当前可用内存:	15323136
结束:	1540294697788

8.4----sum=10000

初始总内存16252928
当前可用内存15965096
消耗的内存287832
开始:	1540294985030
总计:	10000

第一种:静态常量--饿汉式
当前可用内存:	14475208
结束:	1540294985997
线程睡眠1000毫秒

开始:	1540294986997
当前可用内存14475208
消耗的内存1777720
总计:	10000

2.饿汉式,静态代码块
当前可用内存:	10917576
结束:	1540294987916
线程睡眠1000毫秒

开始:	1540294988916
当前可用内存10917576
消耗的内存5335352
总计:	9998

3.懒汉式--常规
当前可用内存:	12036128
结束:	1540294989840
线程睡眠1000毫秒

开始:	1540294990840
当前可用内存12034080
消耗的内存4218848
总计:	10000

4.懒汉式,同步方法
当前可用内存:	9795360
结束:	1540294991761
线程睡眠1000毫秒

开始:	1540294992761
当前可用内存9793264
消耗的内存6459664
总计:	9986

5.懒汉式--同步代码块
当前可用内存:	9340936
结束:	1540294993679
线程睡眠1000毫秒

开始:	1540294994679
当前可用内存9338824
消耗的内存6914104
总计:	10000

6.双重检查
当前可用内存:	7792000
结束:	1540294995598
线程睡眠1000毫秒

开始:	1540294996598
当前可用内存7792000
消耗的内存8463024
总计:	9999

7.静态内部类
当前可用内存:	6106208
结束:	1540294997516
线程睡眠1000毫秒

开始:	1540294998516
当前可用内存6106208
消耗的内存10146720
总计:	9998

8.枚举
当前可用内存:	6363688
结束:	1540294999438

8.5----sum=10 0000

初始总内存16252928
当前可用内存15965096
消耗的内存287832
开始:	1540295055474
总计:	99993

第一种:静态常量--饿汉式
当前可用内存:	6316656
结束:	1540295060124
线程睡眠1000毫秒

开始:	1540295061124
当前可用内存6316656
消耗的内存9936272
总计:	100000

2.饿汉式,静态代码块
当前可用内存:	13416304
结束:	1540295065718
线程睡眠1000毫秒

开始:	1540295066719
当前可用内存13414208
消耗的内存28725440
总计:	99995

3.懒汉式--常规
当前可用内存:	7869048
结束:	1540295071313
线程睡眠1000毫秒

开始:	1540295072313
当前可用内存7866920
消耗的内存34272728
总计:	99996

4.懒汉式,同步方法
当前可用内存:	14200352
结束:	1540295076930
线程睡眠1000毫秒

开始:	1540295077930
当前可用内存14200352
消耗的内存55263712
总计:	99980

5.懒汉式--同步代码块
当前可用内存:	10302304
结束:	1540295082537
线程睡眠1000毫秒

开始:	1540295083537
当前可用内存10302304
消耗的内存59161760
总计:	99993

6.双重检查
当前可用内存:	32648592
结束:	1540295088206
线程睡眠1000毫秒

开始:	1540295089206
当前可用内存32648592
消耗的内存75416176
总计:	99998

7.静态内部类
当前可用内存:	45894856
结束:	1540295093839
线程睡眠1000毫秒

开始:	1540295094839
当前可用内存45894856
消耗的内存62169912
总计:	99999

8.枚举
当前可用内存:	25585288
结束:	1540295099470

8.6----sum=100 0000


初始总内存16252928
当前可用内存15965096
消耗的内存287832
开始:	1540295151282
总计:	999976

第一种:静态常量--饿汉式
当前可用内存:	59587368
结束:	1540295193482
线程睡眠1000毫秒

开始:	1540295194482
当前可用内存59585280
消耗的内存106188032
总计:	999815

2.饿汉式,静态代码块
当前可用内存:	18830360
结束:	1540295244347
线程睡眠1000毫秒

开始:	1540295245347
当前可用内存18828312
消耗的内存240694248
总计:	999937

3.懒汉式--常规
当前可用内存:	1967848
结束:	1540295318183
线程睡眠1000毫秒

开始:	1540295319184
当前可用内存1966792
消耗的内存257556000
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at cn.com.startimes.Singleton.Main4.setThread(Main4.java:13)
	at cn.com.startimes.Singleton.Main.doTest(Main.java:12)
	at cn.com.startimes.Singleton.RealMain.main(RealMain.java:59)
Exception in thread "87082" java.lang.OutOfMemoryError: Java heap space
	at java.util.HashMap.<init>(HashMap.java:187)
	at java.util.HashMap.<init>(HashMap.java:199)
	at java.util.ListResourceBundle.loadLookup(ListResourceBundle.java:172)
	at java.util.ListResourceBundle.handleGetObject(ListResourceBundle.java:106)
	at java.util.ResourceBundle.getObject(ResourceBundle.java:368)
	at java.util.ResourceBundle.getObject(ResourceBundle.java:371)
	at java.util.ResourceBundle.getStringArray(ResourceBundle.java:351)
	at java.text.DateFormatSymbols.initializeData(DateFormatSymbols.java:622)
	at java.text.DateFormatSymbols.<init>(DateFormatSymbols.java:123)
	at java.text.DateFormatSymbols.getCachedInstance(DateFormatSymbols.java:328)
	at java.text.DateFormatSymbols.getInstanceRef(DateFormatSymbols.java:302)
	at java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:498)
	at java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:475)
	at cn.com.startimes.Singleton.Test4.run(Test4.java:15)
	at java.lang.Thread.run(Thread.java:662)
Exception in thread "87086" java.lang.OutOfMemoryError: Java heap space
	at java.lang.Object.clone(Native Method)
	at java.util.TimeZone.clone(TimeZone.java:696)
	at sun.util.calendar.ZoneInfo.clone(ZoneInfo.java:689)
	at java.util.TimeZone.getDefault(TimeZone.java:515)
	at java.text.SimpleDateFormat.initializeCalendar(SimpleDateFormat.java:598)
	at java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:496)
	at java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:475)
	at cn.com.startimes.Singleton.Test4.run(Test4.java:15)
	at java.lang.Thread.run(Thread.java:662)


一起执行发现内存不够,所以呢,一个一个的执行:

8.6.1

初始总内存16252928
当前可用内存15965096
消耗的内存287832
开始:	1540295518312
总计:	999968

第一种:静态常量--饿汉式
当前可用内存:	54538064
结束:	1540295560328
线程睡眠1000毫秒


8.6.2

初始总内存16252928
开始:	1540295611141
当前可用内存15965096
消耗的内存287832
总计:	999975

2.饿汉式,静态代码块
当前可用内存:	21531648
结束:	1540295653102
线程睡眠1000毫秒


8.6.3

初始总内存16252928
开始:	1540295686658
当前可用内存15965096
消耗的内存287832
总计:	999930

3.懒汉式--常规
当前可用内存:	56398800
结束:	1540295730306
线程睡眠1000毫秒


8.6.4

初始总内存16252928
开始:	1540295765798
当前可用内存15965096
消耗的内存287832
总计:	999981

4.懒汉式,同步方法
当前可用内存:	56129152
结束:	1540295808964
线程睡眠1000毫秒


8.6.5

初始总内存16252928
开始:	1540295886300
当前可用内存15965096
消耗的内存287832
总计:	999974

5.懒汉式--同步代码块
当前可用内存:	28563256
结束:	1540295927973
线程睡眠1000毫秒


8.6.6

初始总内存16252928
开始:	1540295968057
当前可用内存15965096
消耗的内存287832
总计:	999958

6.双重检查
当前可用内存:	32765968
结束:	1540296010265
线程睡眠1000毫秒


8.6.7

初始总内存16252928
开始:	1540296051198
当前可用内存15965096
消耗的内存287832
总计:	999969

7.静态内部类
当前可用内存:	56959392
结束:	1540296092718
线程睡眠1000毫秒


8.6.8

初始总内存16252928
开始:	1540296137102
当前可用内存15965096
消耗的内存287832
总计:	999962

8.枚举
当前可用内存:	67777208
结束:	1540296178511

9测试可靠性

说明:之前的测试中list.size因为子线程并没有全部结束,所以输出的结果与预期有差别,这是正常的。

记得修改sum

接下来是测试可靠性的过程与方法:

9.1方法

检测线程数目,当线程数目等于1时(只剩下主线程),输出系统状态(调用单例类的shwo方法)

9.2过程

新建一个带有静态主方法main方法的类:

/**
 * 创建100个线程去访问单例对象的list
 * 同时对list进行增加操作,最后输出list的内容
 * 
 *
 */

public class OneMain {

	public static void main(String[] args) {
		
		Main1 main1 = new Main1();
		main1.doTest(Test1.class);
		
		Main2 main2 = new Main2();
		main2.doTest(Test2.class);
		
		Main3 main3 = new Main3();
		main3.doTest(Test3.class);
		
		Main4 main4 = new Main4();
		main4.doTest(Test4.class);
		
		Main5 main5 = new Main5();
		main5.doTest(Test5.class);
		
		Main6 main6 = new Main6();
		main6.doTest(Test6.class);
		
		Main7 main7 = new Main7();
		main7.doTest(Test7.class);
		
		Main8 main8 = new Main8();
		main8.doTest(Test8.class);
		
		try{
			while(Thread.activeCount() != 1){
				Thread.sleep(5000);
			}
		} catch(Exception e){
			e.getMessage();
		}
		
		System.out.println();
		System.out.println();
		System.out.println();
		System.out.println();
		
		
		System.out.println(Thread.activeCount());
		Singleton1.getInstance().show();
		Singleton2.getInstance().show();
		Singleton3.getInstance().show();
		Singleton4.getInstance().show();
		Singleton5.getInstance().show();
		Singleton6.getInstance().show();
		Singleton7.getInstance().show();
		Singleton8.getInstance().show();
	}

}


9.3结果

总计:	99

第一种:静态常量--饿汉式
当前可用内存:	13085400
结束:	1540296929928
总计:	99

2.饿汉式,静态代码块
当前可用内存:	12831184
结束:	1540296930434
总计:	99

3.懒汉式--常规
当前可用内存:	12576928
结束:	1540296930940
总计:	99

4.懒汉式,同步方法
当前可用内存:	12291264
结束:	1540296931448
总计:	96

5.懒汉式--同步代码块
当前可用内存:	12037016
结束:	1540296931954
总计:	99

6.双重检查
当前可用内存:	11751184
结束:	1540296932461
总计:	98

7.静态内部类
当前可用内存:	11491904
结束:	1540296932968
总计:	99

8.枚举
当前可用内存:	15660968
结束:	1540296933477




1
总计:	99

第一种:静态常量--饿汉式
当前可用内存:	15660968
结束:	1540296933477
总计:	99

2.饿汉式,静态代码块
当前可用内存:	15660968
结束:	1540296933477
总计:	99

3.懒汉式--常规
当前可用内存:	15660968
结束:	1540296933477
总计:	99

4.懒汉式,同步方法
当前可用内存:	15660968
结束:	1540296933477
总计:	96

5.懒汉式--同步代码块
当前可用内存:	15660968
结束:	1540296933477
总计:	99

6.双重检查
当前可用内存:	15660968
结束:	1540296933477
总计:	98

7.静态内部类
当前可用内存:	15660968
结束:	1540296933478
总计:	99

8.枚举
当前可用内存:	15660968
结束:	1540296933478

9.4另一种方式

9.4.1单例类基类增加方法

protected void getSize(){
		System.out.println(list.size());
	}

9.4.2测试主类

/**
 * 创建100个线程去访问单例对象的list
 * 同时对list进行增加操作,最后输出list的内容
 * 
 *
 */

public class OneMain {

	public static void main(String[] args) {
		
		Main1 main1 = new Main1();
		main1.doTest(Test1.class);
		
		Main2 main2 = new Main2();
		main2.doTest(Test2.class);
		
		Main3 main3 = new Main3();
		main3.doTest(Test3.class);
		
		Main4 main4 = new Main4();
		main4.doTest(Test4.class);
		
		Main5 main5 = new Main5();
		main5.doTest(Test5.class);
		
		Main6 main6 = new Main6();
		main6.doTest(Test6.class);
		
		Main7 main7 = new Main7();
		main7.doTest(Test7.class);
		
		Main8 main8 = new Main8();
		main8.doTest(Test8.class);
		
		try{
			while(Thread.activeCount() != 1){
				Thread.sleep(5000);
			}
		} catch(Exception e){
			e.getMessage();
		}
		
		System.out.println();
		System.out.println();
		System.out.println();
		System.out.println();
		
		
		System.out.println(Thread.activeCount());
		Singleton1.getInstance().getSize();
		Singleton2.getInstance().getSize();
		Singleton3.getInstance().getSize();
		Singleton4.getInstance().getSize();
		Singleton5.getInstance().getSize();
		Singleton6.getInstance().getSize();
		Singleton7.getInstance().getSize();
		Singleton8.getInstance().getSize();
	}

}


9.4.3结果

总计:	100

第一种:静态常量--饿汉式
当前可用内存:	13026272
结束:	1540297109882
总计:	99

2.饿汉式,静态代码块
当前可用内存:	12772128
结束:	1540297110389
总计:	96

3.懒汉式--常规
当前可用内存:	12517888
结束:	1540297110894
总计:	99

4.懒汉式,同步方法
当前可用内存:	12232224
结束:	1540297111402
总计:	95

5.懒汉式--同步代码块
当前可用内存:	11978000
结束:	1540297111908
总计:	99

6.双重检查
当前可用内存:	11692288
结束:	1540297112416
总计:	100

7.静态内部类
当前可用内存:	15892832
结束:	1540297112924
总计:	100

8.枚举
当前可用内存:	15544072
结束:	1540297113431




1
100
99
96
99
95
99
100
100

10补充

发现试验结果与预期有一定的区别,所以,使用调试的方式查看具体的值:
首先在主程序:OneMain的主方法中,当线程为1后面的代码处设置断点
结果如下:

10.1第一次测试结果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

10.2第二次测试

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/a18792721831/article/details/83312731