您的位置:首页 > 其它

线程安全的单例模式

2015-07-01 10:21 429 查看
单例模式1:

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个月,又是通过培训中心培训出来的,所以技能肯定有所欠缺,麻烦看官能够指出我的错误。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: