懒汉式
class Single
{
private static Single s = new Single();
private Single(){}
private static Single getInstance()
{
return s;
}
}
饿汉式
class Single
{
private static Single s =null;
private Single(){}
private static Single getInstance()
{
if(s==null)
s= new Single();
return s;
}
}
解决方案
5
题主最近是在面试吧,可以从字面上去理解,懒汉式:不用的时候不去new这个实例,用到才new,饿汗式是先提前new好实例,
一个是省时间占空间 一个花时间省空间 具体可以到网上找找,
一个是省时间占空间 一个花时间省空间 具体可以到网上找找,
10
所谓“懒汉式”与“饿汉式”的区别,是在与建立单例对象的时间不同。
“懒汉式”是在你真正用到的时候才去建这个单例对象:
例如:有个单例对象
private static Student student = null; //不建立对象
Student getInstance(){
if(student == null) { //先判断能否为空
student = new Student(); //懒汉式做法
}
return student;
}
“饿汉式”是在不管你用的用不上,一开始就建立这个单例对象:
例如:有个单例对象
private static Student student = new Student(); //建立对象
Student getInstance(){
return student; //直接返回单例对象
}
“懒汉式”是在你真正用到的时候才去建这个单例对象:
例如:有个单例对象
private static Student student = null; //不建立对象
Student getInstance(){
if(student == null) { //先判断能否为空
student = new Student(); //懒汉式做法
}
return student;
}
“饿汉式”是在不管你用的用不上,一开始就建立这个单例对象:
例如:有个单例对象
private static Student student = new Student(); //建立对象
Student getInstance(){
return student; //直接返回单例对象
}
5
第二种这样写不是线程安全的, java 并发编程实战是这么写的
class Single
{
private volatile static Single s =null; //用volatile保证可见性
private Single(){}
private static Single getInstance()
{
if(s==null){
synchronized(this){
if (s == null)
s= new Single();
}
}
return s;
}
}
class Single
{
private volatile static Single s =null; //用volatile保证可见性
private Single(){}
private static Single getInstance()
{
if(s==null){
synchronized(this){
if (s == null)
s= new Single();
}
}
return s;
}
}
5
明白题主的意思了。在单线程的环境下,单例模式饿汉式和懒汉式没有区别。但是在多线程的环境下,饿汉式没有问题,懒汉式可能会产生初始化多个实例的情况。在多线程的环境下,出错的地方就在if判断这里,没有加线程同步,最高效的保证懒汉式在多线程的环境下,不创建多个对象的代码如下,题主可以参考下:
public class Singleton {
private static Singleton singleton = null;
private Singleton(){}
public static Singleton getInstance(){
if(singleton == null){
synchronized(Singleton.class){
if(singleton ==null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
public class Singleton {
private static Singleton singleton = null;
private Singleton(){}
public static Singleton getInstance(){
if(singleton == null){
synchronized(Singleton.class){
if(singleton ==null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
5
通常单例模式在Java语言中,有两种构建方式:
懒汉方式:指全局的单例实例在第一次被使用时构建
饿汉方式:指全局的单例实例在类装载时构建
具体代码,可以参考下面的帖子:
http://bbs.bccn.net/thread-438043-1-1.html
懒汉方式:指全局的单例实例在第一次被使用时构建
饿汉方式:指全局的单例实例在类装载时构建
具体代码,可以参考下面的帖子:
http://bbs.bccn.net/thread-438043-1-1.html
10
楼上各位都回答的差不多了,本人在这里总结一下:
1 区别: 饿汉式:在类加载的时候,就实例化了单例对象,这种方式其实很常用,单例工厂类一般的职责就是负责提供单例,所以它被加载的时候,目的也是为了获取单例,所以从内存使用上来说,并不存在浪费的现象。当然,假如单例工厂类还负责其他的功能,并在类加载的时候不需要初始化单例对象,那么就另说了,其实这种是设计不好的问题。
饿汉式代码:
1 区别: 饿汉式:在类加载的时候,就实例化了单例对象,这种方式其实很常用,单例工厂类一般的职责就是负责提供单例,所以它被加载的时候,目的也是为了获取单例,所以从内存使用上来说,并不存在浪费的现象。当然,假如单例工厂类还负责其他的功能,并在类加载的时候不需要初始化单例对象,那么就另说了,其实这种是设计不好的问题。
饿汉式代码:
class Single { private final static Single s = new Single(); private Single(){} public static Single getInstance() { return s; } }
懒汉式:和饿汉式的区别,就是为了节约内存,只有在真正使用单例示例的时候才初始化,并不是在类加载的时候进行初始化。
但是在多线程的情况下,会出现并发问题,假如没有同步控制,就无法保证单例,而饿汉式并不存在这个问题,原因是java虚拟机在类加载的时候已经进行了同步控制,一个类中的静态变量只能初始化一次。
多线程场景下的饿汉式写法:
public class Singleton { private static Singleton singleton = null; private Singleton(){} public static Singleton getInstance(){ if(singleton == null){ synchronized(Singleton.class){ if(singleton ==null){ singleton = new Singleton(); } } } return singleton; } }
也许有人会问,为什么不在方法上加上同步,还要这么麻烦,其实这是应对高并发访问场景的,假如方法上加同步,那么全部请求都是排队的,而假如先判断,那么在单例实例化之后,访问就不存在同步控制的问题了。