单例模式
- 1.单例模式
- 2.单例模式实现方式
- 3.构思对比项目
- 3.1对比方式
- 3.2单例基类设计
- 3.3线程基类
- 3.4测试类基类设计
- 4单例模式具体实现
- 4.1静态常量–饿汉式
- 4.2饿汉式,静态代码块
- 4.3懒汉式–常规
- 4.4懒汉式,同步方法
- 4.5懒汉式–同步代码块
- 4.6双重检查
- 4.7静态内部类
- 4.8枚举
- 5.线程类具体实现
- 5.1—4.1
- 5.2–4.2
- 5.3-4.3
- 5.4–4.4
- 5.5–4.5
- 5.6–4.6
- 5.7–4.7
- 5.8–4.8
- 6测试类具体实现
- 6.1–4.1–5.1
- 6.2–4.2–5.2
- 6.3–4.3–5.3
- 6.4–4.4–5.4
- 6.5–4.5–5.5
- 6.6–4.6–5.6
- 6.7–4.7–5.7
- 6.8–4.8–5.8
- 7项目主方法
- 8.测试结果
- 8.1—-sum=10
- 8.2—-sum=100
- 8.3—-sum=1000
- 8.4—-sum=10000
- 8.5—-sum=10 0000
- 8.6—-sum=100 0000
- 8.6.1
- 8.6.2
- 8.6.3
- 8.6.4
- 8.6.5
- 8.6.6
- 8.6.7
- 8.6.8
- 9测试可靠性
- 9.1方法
- 9.2过程
- 9.3结果
- 9.4另一种方式
- 9.4.1单例类基类增加方法
- 9.4.2测试主类
- 9.4.3结果
- 10补充
- 10.1第一次测试结果
- 10.2第二次测试
23种设计模式
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第二次测试
23种设计模式