单例模式
单例模式顾名思义,就是一个类只能有一个实例,这个模式用于需要控制实例数量,或者要节省系统资源的时候,而单例模式的实现的关键在于其构造函数为私有的即private,以下将展示集中单例模式的写法。
一、
public class SingleOne {
private static final SingleOne singleOne = new SingleOne();
private SingleOne(){
}
public static SingleOne getInstance(){
return singleOne;
}
}
这种方法简单粗暴,唯一缺点在于,无论你是否会用到该对象,他都会在类装载时完成实例化,占用内存,但是简单实用,同时jvm保证线程安全。
二、
public class SingleTwo {
private static SingleTwo singleTwo;
private SingleTwo(){
}
public static SingleTwo getInstance(){
if (singleTwo == null){
singleTwo = new SingleTwo();
}
return singleTwo;
}
}
这种方法相较于第一种方法来说是按需来进行初始化的,即只要在使用到该实例时才会进行初始化,但是同时也会带来线程的安全问题,下面将进行测试,采用多线程的方式进行测试,同时打印出每次实例的哈希码(在同一个类中相同实例的哈希码相同),通过测试会发现这其中并不只有一个实例。
public class SingleTwo {
private static SingleTwo singleTwo;
private SingleTwo(){}
public static SingleTwo getInstance(){
if (singleTwo == null){
try {
Thread.sleep(1);
}catch (InterruptedException e){
e.printStackTrace();
}
singleTwo = new SingleTwo();
}
return singleTwo;
}
public static void main(String[] args) {
for (int i = 0; i <100 ; i++) {
new Thread(()-> System.out.println(SingleTwo.getInstance().hashCode())).start();
}
}
}
三、
public class SingleThree {
private static SingleThree singleThree;
private SingleThree(){}
public synchronized static SingleThree getInstance(){
if (singleThree == null){
singleThree = new SingleThree();
}
return singleThree;
}
}
第三种方式是通过给获取实例的方法加锁的方式来达到线程安全的目的,但加锁本身也会带来一定的资源消耗。
四、
public class SingleFive {
private static SingleFive singleFive;
private SingleFive(){}
private static class SingleFiveHolder{
private final static SingleFive SINGLE_FIVE = new SingleFive();
}
public static SingleFive getInstance(){
return SingleFiveHolder.SINGLE_FIVE;
}
}
这种方式算是以上给出的方法中最完美的一种方法,在该类中设置一个私有的内部类,既避免了被无脑加载到内存中造成多余的系统消耗,同时也防止了线程安全问题。