锁定老帖子 主题:关于JAVA单例模式
精华帖 (1) :: 良好帖 (2) :: 新手帖 (7) :: 隐藏帖 (12)
|
|
---|---|
作者 | 正文 |
发表时间:2012-03-15
lunadancer 写道 Fkron 写道 今天和一人讨论以下这几形式的单例,看这样写是否正确??
public class Singleton { private static Singleton st; public static Singleton getInstance() { if (null == st) { return new Singleton(); } return st; } } 他说这样写不对。。晕了。。 可能他是这个意思, 你每次都new一个新的对象那还叫单例么? public class Singleton { private static Singleton st; public static Singleton getInstance() { synchronize(Singleton.class){ if (null == st) { st = new Singleton(); } } return st; } } 哈哈,楼上正解。开始我也以为说的是线程问题。 |
|
返回顶楼 | |
发表时间:2012-03-15
837062099 写道 coollzh 写道 考虑lazy load的话,可以用double check技术。
不过double check有时候也不是100%线程安全的 多线程情况下,直接在方法上加synchronized同步,但是不够效率,事实上,只需要同步一次就可以了。 double check + volatile就100%安全了,取消编译器优化。 public class Singleton { private static volatile Singleton st; private Singleton (){} public static Singleton getInstance() { if (null == st) { synchronized (Singleton.class) { if (st == null) { st = new Singleton(); return st; } } } return st; } } 这个算是终极解决办法了。不过在分步式的环境下,要注意使用单例,因为单例,只是在一个JVM上的单例,多个JVM上的对象并不一样。 |
|
返回顶楼 | |
发表时间:2012-03-15
//懒汉模式 public class Singleton { private static Singleton st; private Singleton(){ } public static Singleton getInstance() { if (null == st) { //处理多线程的问题,如果第一次访问枷锁 之后不在枷锁 synchronized (Singleton.class){ st = new Singleton(); } } return st; } } //饿汉模式 class Singleton1 { private static Singleton1 st = new Singleton1(); private Singleton1(){ } public static Singleton1 getInstance() { return st; } }
|
|
返回顶楼 | |
发表时间:2012-03-15
错了,楼主的确错了。。。大意了
|
|
返回顶楼 | |
发表时间:2012-03-15
http://xupo.iteye.com/blog/463426看看这个吧
|
|
返回顶楼 | |
发表时间:2012-03-15
最后修改:2012-03-15
/** * @author lee * @date Mar 5, 201210:09:12 AM * @version V1.0 * @todo 单例模式属于对象创建型模式,其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点 */ public class Singleton { private static Singleton instance; private static Singleton instance1=new Singleton(); private static Singleton instance2; private static Singleton instance3; private volatile static Singleton instance4; //私有构造方法,避免外部创建实例 private Singleton(){ } //懒汉式单例>当需要的时候,并且发现没有实例的时候,才去初始化. public static Singleton getInstance(){ if(instance==null){ threadSleep(); instance=new Singleton(); } return instance; } //饿汉式单例>管你需要不需要,反正我是饿了,类加载的时候就已经初始化,没有起到延迟加载的效果 public static Singleton getInstance1(){ return instance1; } //对懒汉式进行同步,牺牲了性能,同步的原则应该是尽量对代码块同步,不要对整个方法同步 public static synchronized Singleton getInstance2(){ if(instance2==null){ threadSleep(); instance2=new Singleton(); } return instance2; } //双重检查加锁DCL(double checking lock),只在第一次调用getInstance()时才要同步,提高性能 public static Singleton getInstance3(){ if(instance3==null){ threadSleep(); synchronized (Singleton.class) { if(instance3==null){ instance3=new Singleton(); } } } return instance3; } public static Singleton getInstance4(){ if(instance4==null){ threadSleep(); synchronized (Singleton.class) { if(instance4==null){ instance4=new Singleton(); } } } return instance4; } //让当前线程休眠1秒,模拟多个线程同时访问instance==null之后的临界情况 public static void threadSleep(){ try { System.out.println("当前线程休眠1秒!"); Thread.currentThread().sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } 上面几种是常见的单例写法,下面分别弄几个线程测试一下, public class ThreadTest extends Thread { @Override public void run() { Singleton s=Singleton.getInstance(); System.out.println(s.toString()); /*Singleton s1=Singleton.getInstance1(); System.out.println(s1.toString());*/ /*Singleton s2=Singleton.getInstance2(); System.out.println(s2.toString());*/ /*Singleton s3=Singleton.getInstance3(); System.out.println(s3.toString());*/ } public static void main(String[] args) { for(int i=0;i<3;i++){ ThreadTest test=new ThreadTest(); test.start(); } } } 把RUN方法里的注释,去掉,一次执行一个方法,发现除了第一个在多线程环境下不能实现真正的单例,其他的方法好像都是可以的。。。 网上有说DCL方法在JAVA中也不能实现真正的单例,不过,这测试结果好像也是可以的,还有那个volatile 关键字也不知道是弄啥的? |
|
返回顶楼 | |
发表时间:2012-03-15
单例是相对的。并不能做到完全正确的单例,用户可以通过系列化再反系列化的方式得到多份示例。
|
|
返回顶楼 | |
发表时间:2012-03-15
最后修改:2012-03-15
mfkvfn 写道 单例是相对的。并不能做到完全正确的单例,用户可以通过系列化再反系列化的方式得到多份示例。
只要没有implements Serializable就无法序列化的 即使实现这个接口了,在类里加入readResolve方法返回this即可保证反序列化不会得到多个实例 |
|
返回顶楼 | |
发表时间:2012-03-15
最后修改:2012-03-15
致命伤是没有赋值给st,其次没有私有构造,另外最好加上锁。
|
|
返回顶楼 | |
发表时间:2012-03-15
当然不正确
|
|
返回顶楼 | |