线程安全的单例模式
2015-07-01 10:21
429 查看
单例模式1:
第一种singleton是比较常用的一种单例模式,如果同时有多个线程一起获取这个单例对象的话,可能会出现问题。
1000个线程访问这个对象的结果:
线程2获取单例模式:synchro.Singleton@151574b
线程1获取单例模式:synchro.Singleton@151574b
线程0获取单例模式:synchro.Singleton@151574b
线程3获取单例模式:synchro.Singleton@1d2052b
线程4获取单例模式:synchro.Singleton@1187984
线程6获取单例模式:synchro.Singleton@151574b
线程5获取单例模式:synchro.Singleton@151574b
线程7获取单例模式:synchro.Singleton@151574b
线程10获取单例模式:synchro.Singleton@151574b
可以看到线程3和4分别获取了不同的实例,所以这个单例的写法有缺点。
单例模式2:
饿汉模式:
用饿汉模式试了上万遍,没出现不同实例的问题,除了类加载后就创建对象外,这个难道是不会出现线程安全问题的单例模式吗?
单例模式3:
sychronized修饰方法:试了上万次,也没有发现出现多个实例的问题。。
单例模式4:
使用synchronized代码块包裹new实例的部分,自己用循环一共测试了2万遍,没有发现出现不同实例的情况。
单例模式5:
用volatile修饰静态实例,这个没有测试,网上说这个方法是最好的一种写法。需要用好的办法证明一下。
总结:
除了用第一种懒汉单例模式进行测试出现了多个实例的情况,其他几种各测试了上万次(用循环),基本没有出现多个实例的情况。由于本人工作经验才4个月,又是通过培训中心培训出来的,所以技能肯定有所欠缺,麻烦看官能够指出我的错误。。
package synchro; public class Singleton { private Singleton(){} private static Singleton instance; public static Singleton getInstance(){ if(instance==null){ instance=new Singleton(); return instance; } return instance; } public static void main(String[] args) { for(int i=0;i<1000;i++){ Thread t=new GetClassInfo(); t.setName("线程"+i); t.start(); } } } class GetClassInfo extends Thread{ @Override public void run() { try { Thread.sleep(500); System.out.println(getName()+"获取单例模式:"+Singleton.getInstance()); } catch (InterruptedException e) { e.printStackTrace(); } } }
第一种singleton是比较常用的一种单例模式,如果同时有多个线程一起获取这个单例对象的话,可能会出现问题。
1000个线程访问这个对象的结果:
线程2获取单例模式:synchro.Singleton@151574b
线程1获取单例模式:synchro.Singleton@151574b
线程0获取单例模式:synchro.Singleton@151574b
线程3获取单例模式:synchro.Singleton@1d2052b
线程4获取单例模式:synchro.Singleton@1187984
线程6获取单例模式:synchro.Singleton@151574b
线程5获取单例模式:synchro.Singleton@151574b
线程7获取单例模式:synchro.Singleton@151574b
线程10获取单例模式:synchro.Singleton@151574b
可以看到线程3和4分别获取了不同的实例,所以这个单例的写法有缺点。
单例模式2:
package synchro; public class Singleton2 { private Singleton2(){} private static Singleton2 instance=new Singleton2(); public static Singleton2 getInstance(){ return instance; } public static void main(String[] args) { for(int i=0;i<1000;i++){ Thread t=new GetClassInfo2(); t.setName("线程"+i); t.start(); } } } class GetClassInfo2 extends Thread{ @Override public void run() { try { Thread.sleep(500); System.out.println(getName()+"获取单例模式:"+Singleton2.getInstance()); } catch (InterruptedException e) { e.printStackTrace(); } } }
饿汉模式:
用饿汉模式试了上万遍,没出现不同实例的问题,除了类加载后就创建对象外,这个难道是不会出现线程安全问题的单例模式吗?
单例模式3:
public class Singleton3 { private Singleton3(){} private static Singleton3 instance; public synchronized static Singleton3 getInstance(){ if(instance==null){ instance= new Singleton3(); } return instance; } }
sychronized修饰方法:试了上万次,也没有发现出现多个实例的问题。。
单例模式4:
public class Singleton4 { private Singleton4(){} private static Singleton4 instance; public static Singleton4 getInstance(){ if(instance==null){ synchronized (Singleton4.class) { if(instance==null){ instance=new Singleton4(); } } } return instance; } }
使用synchronized代码块包裹new实例的部分,自己用循环一共测试了2万遍,没有发现出现不同实例的情况。
单例模式5:
public class Singleton4 { private Singleton4(){} private volatile static Singleton4 instance; public static Singleton4 getInstance(){ if(instance==null){ synchronized (Singleton4.class) { if(instance==null){ instance=new Singleton4(); } } } return instance; } }
用volatile修饰静态实例,这个没有测试,网上说这个方法是最好的一种写法。需要用好的办法证明一下。
总结:
除了用第一种懒汉单例模式进行测试出现了多个实例的情况,其他几种各测试了上万次(用循环),基本没有出现多个实例的情况。由于本人工作经验才4个月,又是通过培训中心培训出来的,所以技能肯定有所欠缺,麻烦看官能够指出我的错误。。
相关文章推荐
- POJO和javabean的异同
- UISlider注意事项
- 【Spring学习笔记-MVC-1.0】Spring MVC架构介绍
- Linux版本 网络调试助手 发布
- Android数据库高手秘籍:SQLite命令
- 6月第4周全球域名注册商(国际域名)新增注册量TOP22
- 静态库,动态库
- [leetcode] 107.Binary Tree Level Order Traversal II
- iOS masonry设置六个等高等宽的view
- 浮点数转字符串函数fcvt和gcvt
- js判断访问来源
- 开源框架Tiny之内容组成
- 底价优化
- Activity的生命周期
- 找出一堆数中最小的前K个数
- 在Eclipse中配置Tomcat7.0
- 修改Nginx屏蔽网址的规则的方法
- Stratgy策略模式
- hdu 5208 Where is Bob
- Webrtc Intro - SCTP