线程安全的单例模式

单例模式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个月,又是通过培训中心培训出来的,所以技能肯定有所欠缺,麻烦看官能够指出我的错误。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值