今天在看单例的时候发现以前写的单例可以进一步优化,由于之前在写单例的时候基本的场景都是单线程,所以基本就是这样子:
package test;
/**
* @version 1.0
* @author lujw E-mail: lujw@toone.com.cn
* @date 创建时间:2017年11月16日 上午9:31:00
*/
public class ChinviSingleton {
private static ChinviSingleton instance;
private ChinviSingleton(){}
public static ChinviSingleton getInstance() {
if (instance == null) {
instance = new ChinviSingleton();
}
return instance;
}
}
这种写法呢简单好用,就是线程不安全罢了,指不定什么时候给一次性多几个实例出来,像我这样的强迫症肯定是不能忍受的。
于是,就有这样的写法了
package test;
/**
* @version 2.0
* @author lujw E-mail: lujw@toone.com.cn
* @date 创建时间:2017年11月16日 上午9:31:00
*/
public class ChinviSingleton {
private static ChinviSingleton instance;
private ChinviSingleton(){}
public static synchronized ChinviSingleton getInstance() {
if (instance == null) {
instance = new ChinviSingleton();
}
return instance;
}
}
加了个同步锁,这样就不怕多线程了,p1在拿实例,你先等等,这样保证了不会创建对个实例出来。
虽然是解决了多线程的问题,但是效率变低了,加上锁效率变低这个不用说,单单这个每次都去拿实例这个,都要经过这个锁,已经创建完就其实不用这个所了,所以很烦人,干他。
package test;
/**
* @version 3.0
* @author lujw E-mail: lujw@toone.com.cn
* @date 创建时间:2017年11月16日 上午9:31:00
*/
public class ChinviSingleton {
private static ChinviSingleton instance;
private ChinviSingleton(){}
public static ChinviSingleton getInstance() {
if (instance == null) {
synchronized(ChinviSingleton.class){
if (instance == null) {
instance = new ChinviSingleton();
}
}
}
return instance;
}
}
这个东西呢,很好,直接在类加载器中初始化话,其实能大大减少免疫多线程带来的问题,那这样写:
package test;
/**
* @version 4.0
* @author lujw E-mail: lujw@toone.com.cn
* @date 创建时间:2017年11月16日 上午9:31:00
*/
public class ChinviSingleton {
private static final ChinviSingleton INSTANCE = new ChinviSingleton();
private ChinviSingleton(){}
public static ChinviSingleton getInstance() {
return INSTANCE;
}
}
优雅,好看,完美,非常正。
这个写法也叫饿汉式加载,为什么叫饿汉呢,反正不管用不用,我先加载一个先,呵呵。
虽然这种很完美,但是呢,这种写法是用类加载器加载的,ClassLoader我们开发者管不了,它怎么加载,什么时候加载我们管不了,像我这种强迫症(够了!不要再强调了!)。。。咳咳咳,恩,好,那有没有一个更优雅一下,炫酷一点,安全一下的写法呢,肯定是有的,这个世界最不缺的就是追求完美的大神,以下是大神的写法,我决定以为跟着这个写:
package test;
/**
* @version 5.0
* @author lujw E-mail: lujw@toone.com.cn
* @date 创建时间:2017年11月16日 上午9:31:00
*/
public enum ChinviSingleton {
INSTANCE;
public void funtion() {
}
}
这种方法简直炫酷,没有class,不用管什么线程怎么怎么的,因为本身枚举实例化就是线程安全的,非常优雅,非常简单,调用:ChinviSingleton.INSTANCE.funtion()
哇,炫酷!
----------------------------------炫酷分割线--------------------------------------------
好了今天就是这样,点个赞再走呗!