版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/successA/article/details/79269456
代码段
private static volatile OSSClient ossClient;
private static OSSClient getOssClient() {
if (ossClient == null) {
synchronized (OSSClient.class) {
if (ossClient == null) {
ossClient = new OSSClient(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
Runtime.getRuntime().addShutdownHook(new Thread(() -> ossClient.shutdown()));
}
}
}
return ossClient;
}
关键代码解析
原子性
synchronized 确保当前只有一个线程实例化oss客户端
可见性
volatitle 全局共享变量,在Java5之后,遵循happens-before原则,一旦被改变,立刻写入内存,写优先于读。
有序性
synchronized 保证了线程的有序性
钩子
已经初始化,但是并不启动的线程,jvm退出之前,进行ossClient的关闭。
代码逻辑解析
首先判断ossClient是否为空,如果不为空,就直接返回;如果为空,就先锁定当前的类,允许一个线程进入。
然后再次判断ossClient是否被初始化。如果没有被初始化,就new 一个ossClient;如果被初始化,就直接返回实例化对象。
如果没有通过volatitle 修饰,可能会报错,因为JVM主要进行三个操作:1.给 ossClient 分配内存 2.调用 Singleton 的构造函数来初始化成员变量
3. 将ossClient对象指向分配的内存空间(执行完这步ossClient就为非 null 了),2和3的操作顺序未知,如果先进行3,然后再进行2操作,ossClient不为空,
2还没有完成,返回就会报错。
Java5之后,通过volatitle修饰,保证写优先于读,所以如果判断ossClient 不为空,那么初始化一定完成。
总结
编写优秀的代码,就像欣赏一首美妙的歌曲,美好的事物,谁不喜欢呢~