java单例全解析

总结了两个经典的懒加载单例模式

先上代码:

[java]  view plain  copy
  1. public class ImageLoader {  
  2.   
  3.     private volatile static ImageLoader instance;  
  4.   
  5.     // Returns singleton class instance  
  6.     public static ImageLoader getInstance() {  
  7.         if (instance == null) {  
  8.             synchronized (ImageLoader.class) {  
  9.                 if (instance == null) {  
  10.                     instance = new ImageLoader();  
  11.                 }  
  12.             }  
  13.         }  
  14.         return instance;  
  15.     }  
  16. }  

这是EventBus中的代码。

如果直接给方法加上synchronized。所有getInstance()的调用都要同步了。其实我们只是在第一次new对象的时候要同步。而同步需要消耗性能


因此两次检查是否instance == null,第一个null是为了避免每次都加锁,毕竟这有一定的开销。第二个是为了避免同步问题,比如十个线程同时调用getInstance()方法,都执行了第一步检查instance == null,并且其中一个线程成功获得了锁(执行了synchronized语句),接下来如果没有再一次判断instance == null,则十个线程将生成10对象,这违背了单例的初衷。

上述代码除了有两次检查instance == null,另一个特点是变量instance的类型声明中添加了volatile,因为像下面这种创建对象的语句并不是原子操作,volatile可以使其成为原子操作,避免同步问题。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. instance = new ImageLoader();  

虽说部分JVM没有完全volatile,但是目前主流的JVM貌似已经都支持了,所以这个问题一般可以忽略。



另外推荐一个更好的简洁方法:

使用静态内部类。

public class OssClient {
    //log
    private  Logger logger = LoggerFactory.getLogger(this.getClass());
    //阿里云API的内或外网域名
    private static String END_POINT;
    //阿里云API的密钥Access Key ID
    private static String ACCESS_KEY_ID;
    //阿里云API的密钥Access Key Secret
    private static String ACCESS_KEY_SECRET;
    //阿里云API的BUCKET_NAME
    private static String BUCKET_NAME;
    public static class clientSingletonHolder{
        //init on demand
        static  OSSClient client = new OSSClient(END_POINT,ACCESS_KEY_ID, ACCESS_KEY_SECRET);
    }
    /**
     * 获取阿里云OSS客户端对象
     * */
    public OSSClient getOSSClient(){
        return clientSingletonHolder.client;
    }
}


解释一下,因为java机制规定,内部类clientSingletonHolder只有在getOSSClient()方法第一次调用的时候才会被加载(实现了lazy),而且其加载过程是线程安全的(实现线程安全)。内部类加载的时候实例化一次client

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值