Easy单例模式
时间:2022-04-22
本文章向大家介绍Easy单例模式,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
在学习单例模式前,不妨问自己几个问题:单例模式是怎么来的,单例模式怎么去用?
单例模式是怎么来的?
这就从设计模式起源开始,他是在实际实践中遇到类似情况可以通用经验所得到的总结,一般在其他模块或者方法多次调用类对象,也就是公共模块,用单例模式可以减少内存的消耗。
单例模式怎么去用?
那这个容易,然后很快不到一分钟写完了。
1 public class singleTonEx01 {
2
3 private static singleTonEx01 singleTon;
4
5 public static void main(String args[]) {
6 singleTonEx01 test1=singleTonEx01.getInstance();
7 test1.CommonMethod();
8 }
9
10 // 防止使用new构造函数实例化对象
11 private singleTonEx01() {
12
13 }
14
15 public static singleTonEx01 getInstance() {
16 if(null==singleTon)
17 singleTon=new singleTonEx01();
18 return singleTon;
19 }
20
21 public void CommonMethod() {
22 System.out.println(getClass().getName());
23 }
24
25 }
但这里会有问题,啥问题呢?单线程中是没问题,但是多线程会出现问题,假设两个多线程A与B,A与B同时判断singleTon不为空,那会创建两次,那对于这个问题需要使用同步锁去解决了,下面改造下代码。
public class singleTonEx01 {
private static singleTonEx01 singleTon;
public static void main(String args[]) {
singleTonEx01 test1 = singleTonEx01.getInstance();
test1.CommonMethod();
}
// 防止使用new构造函数实例化对象
private singleTonEx01() {
}
public static singleTonEx01 getInstance() {
synchronized (singleTonEx01.class) {
if (null == singleTon)
singleTon = new singleTonEx01();
}
return singleTon;
}
public void CommonMethod() {
System.out.println(getClass().getName());
}
}
这还不是最好的方法,如果是这样的话每个线程都会使用同步锁代码块,使用同步锁其实是消耗资源的,因此,可以再改进下,在外面锁再加个判断,这样一来提高了效率。(推荐这种写法1)
另外,补充一下,实例变量加上volatile的意义。
创建对象可以分解为如下的3行伪代码memory=allocate(); //1:分配对象的内存空间ctorInstance(memory); //2:初始化对象instance=memory; //3:设置instance指向刚分配的内存地址上面3行代码中的2和3之间,可能会被重排序导致先3后2;
public class singleTonEx01 {
private volatile static singleTonEx01 singleTon;
public static void main(String args[]) {
singleTonEx01 test1 = singleTonEx01.getInstance();
test1.CommonMethod();
}
// 防止使用new构造函数实例化对象
private singleTonEx01() {
}
public static singleTonEx01 getInstance() {
if (singleTon == null) {
synchronized (singleTonEx01.class) {
if (null == singleTon)
singleTon = new singleTonEx01();
}
}
return singleTon;
}
public void CommonMethod() {
System.out.println(getClass().getName());
}
}
其实还有另外两种方法,一种是不管有没有调用都实例化(俗称恶汉式),另一种是静态内部类的方法(推荐这种写法2),线程安全而且高效
public class singleTonEx02 {
private static final singleTonEx02 singleTon=new singleTonEx02();
public static void main(String args[]) {
singleTonEx02 test1 = singleTon;
test1.CommonMethod();
}
// 防止使用new构造函数实例化对象
private singleTonEx02() {
}
public static singleTonEx02 getIntance() {
return singleTon;
}
public void CommonMethod() {
System.out.println(getClass().getName());
}
}
public class singleTonEx03 {
private static class SingleNBClass {
private final static singleTonEx03 singleTonEx03=new singleTonEx03();
}
public static void main(String args[]) {
singleTonEx03 test1 = singleTonEx03.getIntance();
test1.CommonMethod();
}
// 防止使用new构造函数实例化对象
private singleTonEx03() {
}
public static final singleTonEx03 getIntance() {
return SingleNBClass.singleTonEx03;
}
public void CommonMethod() {
System.out.println(getClass().getName());
}
}
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Linux CentOS 6.5 卸载、tar安装MySQL的教程
- Linux CentOS 6.5 ifconfig查询不到ip的解决方法
- 打卡群2刷题总结1009——二叉树的中序遍历
- 解决Ubuntu 18.04安装VMwareTools错误问题
- 对linux下syslogd以及syslog.conf文件的解读说明
- Linux下安装tomcat并部署网站(推荐)
- 解决Linux中ifconfig和addr查看不到ip问题
- 【软件测试】面试中问到Linux命令,你都答上来了吗?【送书】
- Linux用户自定义at、cron计划任务执行的方法
- Linux下Oracle设置定时任务备份数据库的教程
- centos8 使用yum 安装 rabbitmq的教程
- linux exa命令(比ls更好的展示文件体验)
- 浅谈linux kernel对于浮点运算的支持
- PyTorch版YOLOv4更新了,不仅适用于自定义数据集,还集成了注意力和MobileNet
- Apache shiro的简单介绍与使用教程(与spring整合使用)