单例 ------ JAVA实现
单例:只能实例化一个对象,使用场景比如打印机。
最推荐的是采用饿汉式;双重校验锁用到了大量的语法,不能保证这些语法在所用场合一定没问题,所以不是很推荐;总之简单的才是最好的,就饿汉式!!!
C++ 创建变量可以通过 类名 对象名,但是 JAVA 不行
C++ new 出来的对象需要手动回收,但是 JAVA 可以自动回收
C++ new 出来的对象需要用指针接收,但是 JAVA 对象变量就可以接收,或者说 JAVA 的对象变量就是指针
1、(懒汉,线程安全 ------ 不推荐)
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
说明:在方法调用上加了同步,虽然线程安全了,但是每次都要同步,会影响性能,毕竟99%的情况下是不需要同步的
2、(饿汉 ------ 推荐)
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
说明:instance在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载。所以,会出现在使用对象前就创建好,占用了资源
3、(静态内部类 ------ 推荐)
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
说明:第三种和第二种的区别在于,第三种类被装载也不会实例化对象,一定要调用 getInstance() 才会实例化,而且只实例化一次。
4、(双重校验锁 ------ 一般推荐<理解麻烦>)
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton (){}
public static Singleton getSingleton() {
if (uniqueInstance == null) { // #1
synchronized (Singleton.class) { // #2
if (uniqueInstance == null) { // #3
uniqueInstance = new Singleton(); // #4
}
}
}
return singleton;
}
}
说明:和第一种方式比,这种方式只会第一次调用创建对象时使用同步锁
对象singleton 用 volatile 修饰,原因举例如下:
1. thread2进入#1, 假设这时子线程的uniqueInstance为空(java内存模型会从主线程拷贝一份uniqueInstance=null到子线程thread2),然后thread2让出CPU资源给thread3
2. thread3进入#1, 这时子线程的uniqueInstance还是为空(java内存模型会从主线程拷贝一份uniqueInstance=null到子线程thread3),然后thread3让出CPU资源给thread2
3. thread2会依次执行#2,#3,#4,最终在thread2里面实例化了uniqueInstance(由于是volatile修饰的变量,会马上同步到主线程的变量去),thread2执行完毕让出CPU资源给thread3
4. thread3接着#1跑下去,跑到#3的时候,会又一次从主线程拷贝一份uniqueInstance!=null回来,所以thread3就不会实例化对象
上面解释的是 volatile 保证变量可见性的体现,使每个线程得到的变量来源都是唯一的;同时 volatile 还能保证变量的有序性," new Singleton "的执行其实是分三步走,第一:分配内存,第二:执行构造函数,第三:赋值,准确的说应该是引用;如果没有 volatile 修饰,在保证结果的情况下(单线程,或者是本线程中)编译器可能会打乱执行顺序,如果有另外一个线程在执行 #1 判断变量不为nll,但是此变量没有执行构造函数,获取的对象是不完整的,程序就可能发生错误。java的volatile顺序性方面比C++强,能保证此顺序执行。
volatile 防止编译器把两个 if 优化成一个 if 。
疑问:
1、如果赋值不是原子操作,会不会出现,没完全赋值完成就被另外一个线程使用了
单例 ------ JAVA实现的更多相关文章
- 单例 (JAVA)
java中单例模式是一种常见的设计模式,以下是它的特点: 单例类只能有一个实例. 单例类必须自己创建自己的唯一实例. 单例类必须给所有其他对象提供这一实例 第一种(懒汉,线程不安全): 1 publ ...
- javaWeb项目中到底什么是单例,多例
你用杯子喝可乐,喝完了不刷,继续去倒果汁喝,就是单例.你用杯子喝可乐,直接扔了杯子,换个杯子去倒果汁喝,就是多例. 数据库连接池就是单例模式,有且仅有一个连接池管理者,管理多个连接池对象. 1. 什么 ...
- java 单例
Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍两种:懒汉式单例.饿汉式单例. 饿汉式和懒汉式区别 从名字上来说,饿汉和懒汉, 饿汉就是类一旦加载,就把单例初始化完成,保证 ...
- Java设计模式之单例
一.Java中的单例: 特点: ① 单例类只有一个实例 ② 单例类必须自己创建自己唯一实例 ③ 单例类必须给所有其他对象提供这一实例 二.两种模式: ①懒汉式单例<线程不安全> 在类加载时 ...
- java单例的几种实现方法
java单例的几种实现方法: 方式1: public class Something { private Something() {} private static class LazyHolder ...
- Java 多线程之单例设计模式
转载:https://segmentfault.com/a/1190000007504892 概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍两种:懒汉式单例.饿汉 ...
- java单例类/
java单例类 一个类只能创建一个实例,那么这个类就是一个单例类 可以重写toString方法 输出想要输出的内容 可以重写equcal来比较想要比较的内容是否相等 对于final修饰的成员变量 一 ...
- java单例-积木系列
一步步知识点归纳吧,把以前似懂非懂,了解表面,知道点不知道面的知识归一下档. 懒汉式单例: 私有化构造函数,阻止外界实例话对象,调用getInstance静态方法,判断是否已经实例化. 为什么是懒 ...
- 如何防止JAVA反射对单例类的攻击?
在我的上篇随笔中,我们知道了创建单例类有以下几种方式: (1).饿汉式; (2).懒汉式(.加同步锁的懒汉式.加双重校验锁的懒汉式.防止指令重排优化的懒汉式); (3).登记式单例模式; (4).静态 ...
随机推荐
- sparkML原始数据转换成label-features方法
数据1:kaggle-旧金山犯罪分类数据 格式如下: Dates,Category,Descript,DayOfWeek,PdDistrict,Resolution,Address,X,Y -- :: ...
- parity 注记词
spousal tint untold around rosy daintily unrated sheep choice showpiece chirping gala
- php 面试题
1.通过哪一个函数,可以把错误转换为异常处理? A:set_error_handlerB:error_reportingC:error2exceptionD:catch 正确答案:A 答案分析:set ...
- C#通过gridview导出excel
[CustomAuthorize] public FileResult ExportQuestionCenterExcel(SearchBaseQuestion search) ...
- Ubuntu14.04下部署FastDFS 5.08+Nginx 1.9.14
最新的版本可以在这里获取,目前下载的最新版本是5.08,更新于2016-02-03.在这里可以找到更多的说明. 下载好后,server端分为两个部分,一个是tracker,一个是storage.顾 ...
- axis2调用webService几种方式
主要有三种方式: 第一RPC方式,不生成客户端代码 第二,document方式,不生成客户端代码 第三,用wsdl2java工具,生成客户端方式调用 java代码: package samples.q ...
- Daily Scrum 11
今天我们小组开会内容分为以下部分: part 1: 针对学长的搜索算法进行优化,每人发表自己的看法; part 2:对积分系统.防滥用.搜索算法优化部分代码任务的讨论和分工: part 3:进行明日的 ...
- 20172333 2017-2018-2 《Java程序设计》第7周学习总结
20172333 2017-2018-2 <Java程序设计>第7周学习总结 教材学习内容 1.继承是创建新类的快捷方式之一,继承可以使用父类的所有方法及对象. 2.继承具有单向性,父类不 ...
- noauth authentication required redis
解决方案: 这是出现了认证的问题,是因为设置了认证密码. 127.0.0.1:6379> auth "yourpassword" 例如:
- tweenjs缓动算法使用小实例
这里的tweenjs不是依托于createjs的tewwnjs,而是一系列缓动算法集合.因为本身是算法,可以用在各个业务场景中,这也正是总结学习它的价值所在.tweenjs代码详情: /* * Twe ...